Copepod Collection
Copepods were collected at approximately weekly intervals from Lake
Champlain (Burlington Fishing Pier). Plankton was collected from the top
3 meters using a 250 um mesh net.
# Lake Champlain near Burlington, VT
siteNumber = "04294500"
ChamplainInfo = readNWISsite(siteNumber)
parameterCd = "00010"
startDate = "2023-01-01"
endDate = ""
#statCd = c("00001", "00002","00003", "00011") # 1 - max, 2 - min, 3 = mean
# Constructs the URL for the data wanted then downloads the data
url = constructNWISURL(siteNumbers = siteNumber, parameterCd = parameterCd,
startDate = startDate, endDate = endDate, service = "uv")
temp_data = importWaterML1(url, asDateTime = T) %>%
mutate("date" = as.Date(dateTime)) %>%
select(date, "temp" = X_00010_00000)
Collections began in late May 2023. Several gaps are present, but
collections have continued at roughly weekly intervals since then.
Copepods from 24 collections were used to make a total of 624 thermal
limit measurements. Over this time period, collection temperatures
ranged from 8.5 to 26.5°C.
There is substantial variation in thermal limits across the species
collected. There is also some degree of variation within the species,
with thermal limits increasing slightly during the summer.
## Daily values for the period examined by dataset
collection_conditions = temp_data %>%
ungroup() %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
med_temp = median(temp),
var_temp = var(temp),
min_temp = min(temp),
max_temp = max(temp)) %>%
mutate("range_temp" = max_temp - min_temp,
date = as.Date(date)) %>%
ungroup() %>%
filter(date >= (min(as.Date(full_data$collection_date)) - 7))
## Mean female thermal limits for each species, grouped by collection
species_summaries = full_data %>%
#filter(sex == "female") %>%
group_by(sp_name, collection_date, collection_temp) %>%
summarise("mean_ctmax" = mean(ctmax),
"sample_size" = n(),
"ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
"ctmax_var" = var(ctmax),
"mean_size" = mean(size),
"size_st_err" = (sd(size) / sqrt(sample_size)),
"size_var" = var(size)) %>%
ungroup() %>%
complete(sp_name, collection_date) %>%
arrange(desc(sample_size))
adult_summaries = full_data %>%
filter(sex == "female") %>%
group_by(sp_name, collection_date, collection_temp) %>%
summarise("mean_ctmax" = mean(ctmax),
"sample_size" = n(),
"ctmax_st_err" = (sd(ctmax) / sqrt(sample_size)),
"ctmax_var" = var(ctmax),
"mean_size" = mean(size),
"size_st_err" = (sd(size) / sqrt(sample_size)),
"size_var" = var(size)) %>%
ungroup() %>%
complete(sp_name, collection_date) %>%
arrange(desc(sample_size))
ggplot() +
geom_vline(data = unique(select(full_data, collection_date)),
aes(xintercept = as.Date(collection_date)),
colour = "grey90",
linewidth = 1) +
geom_line(data = collection_conditions,
aes(x = as.Date(date), y = mean_temp),
colour = "black",
linewidth = 2) +
# geom_errorbar(data = species_summaries,
# aes(x = as.Date(collection_date),
# ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
# colour = sp_name),
# position = position_dodge(width = 1),
# width = 5, linewidth = 1) +
geom_point(data = adult_summaries,
aes(x = as.Date(collection_date), y = mean_ctmax, colour = sp_name, size = sample_size)) +
scale_colour_manual(values = species_cols) +
labs(x = "Date",
y = "Temperature (°C)",
colour = "Species",
size = "Sample Size") +
theme_matt() +
theme(legend.position = "right")

Size also varied both between and within species.
ggplot() +
geom_vline(data = unique(select(full_data, collection_date)),
aes(xintercept = as.Date(collection_date)),
colour = "grey90",
linewidth = 1) +
geom_line(data = collection_conditions,
aes(x = as.Date(date), y = mean_temp),
colour = "black",
linewidth = 2) +
# geom_errorbar(data = species_summaries,
# aes(x = as.Date(collection_date),
# ymin = mean_ctmax - ctmax_st_err, ymax = mean_ctmax + ctmax_st_err,
# colour = sp_name),
# position = position_dodge(width = 1),
# width = 5, linewidth = 1) +
geom_point(data = adult_summaries,
aes(x = as.Date(collection_date), y = mean_size * 40, colour = sp_name, size = sample_size),
position = position_dodge(width = 1)) +
scale_colour_manual(values = species_cols) +
scale_y_continuous(
name = "Temperature", # Features of the first axis
sec.axis = sec_axis(~./40, name="Prosome Length (mm)"), # Add a second axis and specify its features
breaks = c(0,5,10,15,20,25,30)
) +
labs(x = "Date",
y = "Temperature (°C)",
colour = "Species") +
theme_matt() +
theme(legend.position = "right")

For the three species with the most data (Skistodiaptomus,
L. minutus, Epischura), shown below is CTmax and body
size, plotted against the day of the year for each sex/stage
separately.
ctmax_feature = full_data %>%
mutate(doy = yday(collection_date)) %>%
filter(sp_name %in% c("Skistodiaptomus oregonensis", "Leptodiaptomus minutus","Epischura lacustris")) %>%
ggplot(aes(x = as.Date(collection_date), y = ctmax, colour = sp_name)) +
facet_grid(sp_name~sex) +
geom_point() +
scale_colour_manual(values = species_cols) +
labs(x = "Day of the Year",
y = "CTmax (°C)") +
guides(color = FALSE) +
theme_matt_facets() +
theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))
size_feature = full_data %>%
mutate(doy = yday(collection_date)) %>%
filter(sp_name %in% c("Skistodiaptomus oregonensis", "Leptodiaptomus minutus", "Epischura lacustris")) %>%
ggplot(aes(x = as.Date(collection_date), y = size, colour = sp_name)) +
facet_grid(sp_name~sex) +
geom_point() +
scale_colour_manual(values = species_cols) +
labs(x = "Day of the Year",
y = "Size (mm)") +
guides(color = FALSE) +
theme_matt_facets() +
theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))
ggarrange(ctmax_feature, size_feature, common.legend = T, legend = "bottom")

Temperature Variability
Lake Champlain is highly seasonal, with both average temperatures and
temperature variability changing throughout the year. These patterns in
the experienced thermal environment may drive the observed variation in
copepod thermal limits. However, the time period affecting copepod
thermal limits is unknown. Depending the on the duration of time
considered, there are large changes in the experienced environment, in
particular regarding the temperature range and variance. Consider for
example three time periods: the day of collection, one week prior to
collection, and four weeks prior to collection. While the overall
pattern is similar, we can see that, unsurprisingly, considering longer
periods of time results in larger ranges and slightly changes the
pattern of variance experienced.
## Daily values
daily_temp_data = temp_data %>%
ungroup() %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
med_temp = median(temp),
var_temp = var(temp),
min_temp = min(temp),
max_temp = max(temp)) %>%
mutate("range_temp" = max_temp - min_temp)
day_prior_temp_data = temp_data %>%
ungroup() %>%
group_by(date) %>%
summarise(mean_temp = mean(temp),
med_temp = median(temp),
var_temp = var(temp),
min_temp = min(temp),
max_temp = max(temp)) %>%
mutate(date = date + 1) %>%
rename_with(.fn = ~ paste0("prior_day_", .x), .cols = c(-date))
daily_plot = daily_temp_data %>%
pivot_longer(cols = c(-date),
names_to = "parameter",
values_to = "temp") %>%
ggplot(aes(x = date, y = temp, colour = parameter)) +
geom_line(linewidth = 1) +
scale_colour_manual(values = c(
"mean_temp" = "olivedrab3",
"med_temp" = "seagreen3",
"max_temp" = "tomato",
"min_temp" = "dodgerblue",
"range_temp" = "goldenrod3",
"var_temp" = "darkgoldenrod1"
)) +
scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
ggtitle("Daily Values") +
labs(y = "Temperature (°C)",
x = "") +
theme_bw(base_size = 20) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
## Defining the function to get predictor values for periods of different lengths
get_predictors = function(daily_values, raw_temp, n_days){
prefix = str_replace_all(xfun::numbers_to_words(n_days), pattern = " ", replacement = "-")
mean_values = daily_values %>%
ungroup() %>%
mutate(mean_max = slide_vec(.x = max_temp, .f = mean, .before = n_days, .complete = T),
mean_min = slide_vec(.x = min_temp, .f = mean, .before = n_days, .complete = T),
mean_range = slide_vec(.x = range_temp, .f = mean, .before = n_days, .complete = T)) %>%
select(date, mean_max, mean_min, mean_range) %>%
rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))
period_values = raw_temp %>%
mutate(mean = slide_index_mean(temp, i = date, before = days(n_days),
na_rm = T),
max = slide_index_max(temp, i = date, before = days(n_days),
na_rm = T),
min = slide_index_min(temp, i = date, before = days(n_days),
na_rm = T),
med = slide_index_dbl(temp, .i = date, .before = days(n_days),
na_rm = T, .f = median),
var = slide_index_dbl(temp, .i = date, .before = days(n_days),
.f = var),
range = max - min) %>%
select(-temp) %>%
distinct() %>%
rename_with( ~ paste(prefix, "day", .x, sep = "_"), .cols = c(-date))%>%
inner_join(mean_values, by = c("date")) %>%
drop_na()
return(period_values)
}
# ## Getting predictor variables for different periods
#
# ### Short (three days)
# three_day_temps = get_predictors(daily_values = daily_temp_data,
# raw_temp = temp_data,
# n_days = 3)
#
# ### ONE WEEK
week_temps = get_predictors(daily_values = daily_temp_data,
raw_temp = temp_data,
n_days = 7)
week_plot = week_temps %>%
pivot_longer(cols = c(-date),
names_to = "parameter",
values_to = "temp") %>%
filter(parameter %in% c("seven_day_mean",
"seven_day_med",
"seven_day_max",
"seven_day_min",
"seven_day_var",
"seven_day_range")) %>%
mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
ggplot(aes(x = date, y = temp, colour = parameter)) +
geom_line(linewidth = 1) +
scale_colour_manual(values = c(
"mean_temp" = "olivedrab3",
"med_temp" = "seagreen3",
"max_temp" = "tomato",
"min_temp" = "dodgerblue",
"range_temp" = "goldenrod3",
"var_temp" = "darkgoldenrod1"
)) +
scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
ggtitle("One Week") +
labs(y = "Temperature (°C)",
x = "") +
theme_bw(base_size = 20) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
#
#
# ### TWO WEEKS
# two_week_temps = get_predictors(daily_values = daily_temp_data,
# raw_temp = temp_data,
# n_days = 14)
#
# two_week_plot = two_week_temps %>%
# pivot_longer(cols = c(-date),
# names_to = "parameter",
# values_to = "temp") %>%
# filter(parameter %in% c("fourteen_day_mean",
# "fourteen_day_med",
# "fourteen_day_max",
# "fourteen_day_min",
# "fourteen_day_var",
# "fourteen_day_range")) %>%
# mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
# ggplot(aes(x = date, y = temp, colour = parameter)) +
# geom_line(linewidth = 1) +
# scale_colour_manual(values = c(
# "mean_temp" = "olivedrab3",
# "med_temp" = "seagreen3",
# "max_temp" = "tomato",
# "min_temp" = "dodgerblue",
# "range_temp" = "goldenrod3",
# "var_temp" = "darkgoldenrod1"
# )) +
# scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
# ggtitle("Two Weeks") +
# labs(y = "Temperature (°C)",
# x = "") +
# theme_bw(base_size = 20) +
# theme(panel.grid = element_blank(),
# axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
#
#
# ### FOUR WEEKS
four_week_temps = get_predictors(daily_values = daily_temp_data,
raw_temp = temp_data,
n_days = 28)
four_week_plot = four_week_temps %>%
pivot_longer(cols = c(-date),
names_to = "parameter",
values_to = "temp") %>%
filter(parameter %in% c("twenty-eight_day_mean",
"twenty-eight_day_med",
"twenty-eight_day_max",
"twenty-eight_day_min",
"twenty-eight_day_var",
"twenty-eight_day_range")) %>%
mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
ggplot(aes(x = date, y = temp, colour = parameter)) +
geom_line(linewidth = 1) +
scale_colour_manual(values = c(
"mean_temp" = "olivedrab3",
"med_temp" = "seagreen3",
"max_temp" = "tomato",
"min_temp" = "dodgerblue",
"range_temp" = "goldenrod3",
"var_temp" = "darkgoldenrod1"
)) +
scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
ggtitle("Four Weeks") +
labs(y = "Temperature (°C)",
x = "") +
theme_bw(base_size = 20) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
#
#
# ### EIGHT WEEKS
# eight_week_temps = get_predictors(daily_values = daily_temp_data,
# raw_temp = temp_data,
# n_days = 56)
#
# eight_week_plot = eight_week_temps %>%
# pivot_longer(cols = c(-date),
# names_to = "parameter",
# values_to = "temp") %>%
# filter(parameter %in% c("fifty-six_day_mean",
# "fifty-six_day_med",
# "fifty-six_day_max",
# "fifty-six_day_min",
# "fifty-six_day_var",
# "fifty-six_day_range")) %>%
# mutate(parameter = paste(word(parameter, start = 3, sep = fixed("_")), "_temp", sep = "")) %>%
# ggplot(aes(x = date, y = temp, colour = parameter)) +
# geom_line(linewidth = 1) +
# scale_colour_manual(values = c(
# "mean_temp" = "olivedrab3",
# "med_temp" = "seagreen3",
# "max_temp" = "tomato",
# "min_temp" = "dodgerblue",
# "range_temp" = "goldenrod3",
# "var_temp" = "darkgoldenrod1"
# )) +
# scale_x_continuous(breaks = as.Date(c("2023-01-01", "2023-04-01", "2023-07-01"))) +
# ggtitle("Eight Weeks") +
# labs(y = "Temperature (°C)",
# x = "") +
# theme_bw(base_size = 20) +
# theme(panel.grid = element_blank(),
# axis.text.x = element_text(angle = 270, hjust = 0, vjust = 0.5))
#
ggarrange(daily_plot, week_plot, four_week_plot,
common.legend = T, nrow = 1, legend = "bottom")

The different time periods examined by this climate data highlights
that the relationship between minimum and maximum temperatures changes
based on the window examined. For example, minimum and maximum
temperatures experienced over weekly intervals are closely linked,
whereas there is a distinct seasonal cycle in the relationship between
minimum and maximum temperatures experienced over periods of four
weeks.
one_week_doy_data = week_temps %>%
mutate(doy = yday(date))
one_week_temp_circle = ggplot(one_week_doy_data, aes(x = seven_day_mean_max, y = seven_day_mean_min, colour = doy)) +
geom_point() +
scale_colour_gradient2(
high = "dodgerblue4",
mid = "coral2",
low = "dodgerblue4",
midpoint = 182.5) +
labs(x = "Max. Temp. (°C)",
y = "Min. Temp. (°C)") +
labs(x = "Max. Temp. (°C)",
y = "Min. Temp. (°C)") +
ggtitle("One Week") +
theme_matt()
four_week_doy_data = four_week_temps %>%
mutate(doy = yday(date))
four_week_temp_circle = ggplot(four_week_doy_data, aes(x = `twenty-eight_day_max`, y = `twenty-eight_day_min`, colour = doy)) +
geom_point() +
scale_colour_gradient2(
high = "dodgerblue4",
mid = "coral2",
low = "dodgerblue4",
midpoint = 182.5) +
labs(x = "Max. Temp. (°C)",
y = "Min. Temp. (°C)") +
ggtitle("Four Week") +
theme_matt()
ggarrange(one_week_temp_circle, four_week_temp_circle,
common.legend = T, legend = "bottom")

The thermal environment over any period of time may drive patterns in
thermal acclimation. To explore the potential effects of different
acclimation windows, we examined the correlation between thermal limits
and different representations of the thermal environment for different
periods of time. Shown below are the correlation coefficients for these
relationships. Each facet shows the relationship for a different
dimension of the thermal environment. Correlation coefficients are
plotted for different durations, for species that were collected more
than five times. Only data for mature female copepods was included.
We can see that, in general, copepods are responding to proximate
cues from the thermal environment, with correlations generally dropping
off substantially as acclimation window duration increases. An exception
is Epischura lacustris, which appears to be responding to
maximum temperatures experienced over a 20 day time period.
### Pulling predictors and measuring correlations for much finer timescales; 1-56 days
words_to_numbers <- function(s) {
s <- stringr::str_to_lower(s)
for (i in 0:56)
s <- stringr::str_replace_all(s, words(i), as.character(i))
s
}
num_colls = full_data %>%
filter(sex == "female") %>%
select(collection_date, sp_name) %>%
distinct() %>%
count(sp_name) %>%
filter(n >= 5)
corr_vals = data.frame()
dur_vals = c(1:50)
for(i in dur_vals){
duration_temps = get_predictors(daily_values = daily_temp_data,
raw_temp = temp_data,
n_days = i) %>%
filter(date %in% as_date(unique(full_data$collection_date)))
corr_data = full_data %>%
filter(sp_name %in% num_colls$sp_name) %>%
filter(sex == "female") %>%
mutate(collection_date = as.Date(collection_date)) %>%
inner_join(duration_temps, join_by(collection_date == date)) %>%
pivot_longer(cols = c(collection_temp, contains("day_")),
values_to = "value",
names_to = "predictor") %>%
group_by(sp_name, predictor) %>%
summarise(correlation = cor.test(ctmax, value)$estimate,
p.value = cor.test(ctmax, value)$p.value,
ci_low = cor.test(ctmax, value)$conf.int[1],
ci_high = cor.test(ctmax, value)$conf.int[2]) %>%
filter(predictor != "collection_temp") %>%
mutate(sig = ifelse(p.value <0.05, "Sig.", "Non Sig.")) %>%
separate(predictor, "_day_", into = c(NA, "parameter")) %>%
mutate(duration = i)
corr_vals = bind_rows(corr_vals, corr_data)
}
coll_corr = full_data %>%
filter(sp_name %in% num_colls$sp_name) %>%
filter(sex == "female") %>%
group_by(sp_name) %>%
summarise(correlation = cor.test(ctmax, collection_temp)$estimate,
p.value = cor.test(ctmax, collection_temp)$p.value,
ci_low = cor.test(ctmax, collection_temp)$conf.int[1],
ci_high = cor.test(ctmax, collection_temp)$conf.int[2]) %>%
mutate(sig = ifelse(p.value <0.05, "Sig.", "Non Sig.")) %>%
mutate(duration = 0,
parameter = "coll_temp")
corr_vals = corr_vals %>%
mutate(duration = as.numeric(duration)) %>%
bind_rows(coll_corr)
corr_vals %>%
mutate(parameter = fct_relevel(parameter, c("min", "max", "range",
"mean", "med", "var",
"mean_min", "mean_max", "mean_range"))) %>%
ggplot(aes(x = duration, y = correlation, colour = sp_name)) +
facet_wrap(.~parameter) +
geom_hline(yintercept = 0) +
geom_line(linewidth = 1) +
scale_colour_manual(values = species_cols) +
labs(x = "Duration (days)",
y = "Correlation",
colour = "Species") +
theme_matt_facets()

Shown here are the top three factors for each species.
#
# corr_vals = full_data %>%
# filter(sp_name %in% num_colls$sp_name) %>%
# filter(sex == "female") %>%
# mutate(collection_date = as.Date(collection_date)) %>%
# full_join(temp_predictors, join_by(collection_date == date)) %>%
# pivot_longer(cols = c(collection_temp, mean_temp:tail(names(.), 1)),
# values_to = "value",
# names_to = "predictor") %>%
# group_by(sp_name, predictor) %>%
# summarise(correlation = cor.test(ctmax, value)$estimate,
# p.value = cor.test(ctmax, value)$p.value,
# ci_low = cor.test(ctmax, value)$conf.int[1],
# ci_high = cor.test(ctmax, value)$conf.int[2]) %>%
# mutate(sig = ifelse(p.value <0.05, "Sig.", "Non Sig."))
corr_vals %>%
filter(sig == "Sig.") %>%
drop_na(correlation) %>%
group_by(sp_name) %>%
arrange(desc(correlation)) %>%
slice_head(n = 3) %>%
select("Species" = sp_name, "Predictor" = parameter, "Duration" = duration, "Correlation" = correlation, "P-Value" = p.value) %>%
knitr::kable(align = "c")
| Epischura lacustris |
max |
20 |
0.8808650 |
0.0000000 |
| Epischura lacustris |
max |
21 |
0.8793394 |
0.0000000 |
| Epischura lacustris |
max |
19 |
0.8776958 |
0.0000000 |
| Leptodiaptomus minutus |
max |
8 |
0.6929898 |
0.0000000 |
| Leptodiaptomus minutus |
max |
10 |
0.6919056 |
0.0000000 |
| Leptodiaptomus minutus |
max |
9 |
0.6919003 |
0.0000000 |
| Leptodiaptomus sicilis |
max |
4 |
0.4213943 |
0.0003834 |
| Leptodiaptomus sicilis |
max |
3 |
0.4137401 |
0.0005010 |
| Leptodiaptomus sicilis |
max |
5 |
0.4049398 |
0.0006762 |
| Skistodiaptomus oregonensis |
max |
2 |
0.6551011 |
0.0000000 |
| Skistodiaptomus oregonensis |
mean_max |
2 |
0.6460239 |
0.0000000 |
| Skistodiaptomus oregonensis |
max |
1 |
0.6460066 |
0.0000000 |
Trait Variation
# ctmax_plot = full_data %>%
# mutate( #sp_name = str_replace(sp_name, pattern = " ",
# # replacement = "\n"),
# sp_name = fct_reorder(sp_name, ctmax, mean)) %>%
# ggplot(aes(y = sp_name, x = ctmax)) +
# geom_point(aes(colour= sp_name_sub),
# position = position_dodge(width = 0.3),
# size = 4) +
# scale_colour_manual(values = species_cols) +
# xlab(NULL) +
# labs(y = "",
# x = "CTmax (°C)",
# colour = "Group") +
# theme_matt() +
# theme(legend.position = "none")
#
# size_plot = full_data %>%
# mutate(sp_name = fct_reorder(sp_name, ctmax, mean)) %>%
# ggplot(aes(y = sp_name, x = size)) +
# geom_point(aes(colour= sp_name_sub),
# position = position_dodge(width = 0.3),
# size = 4) +
# scale_colour_manual(values = species_cols) +
# labs(x = "Prosome Length (mm)",
# y = "",
# colour = "Group") +
# guides(color = guide_legend(ncol = 1)) +
# theme_matt(base_size = ) +
# theme(legend.position = "right",
# axis.text.y = element_blank(),
# plot.margin = margin(0, 0, 0, 0,"cm"))
#
# trait_plot = ctmax_plot + size_plot
# trait_plot
Shown below are the clutch size distributions for the three
diaptomiid species, which produce egg sacs that allow for easy
quantification of fecundity.
full_data %>%
drop_na(fecundity) %>%
ggplot(aes(x = fecundity, fill = sp_name_sub)) +
facet_wrap(.~sp_name_sub, ncol = 1) +
geom_histogram(binwidth = 2) +
scale_fill_manual(values = species_cols) +
labs(x = "Fecundity (# Eggs)") +
theme_matt_facets() +
theme(legend.position = "none")

One of the main aims of this project is to examine the patterns and
processes driving variation in upper thermal limits across these species
of copepods.
Variation with temperature
We expect one of the primary drivers of copepod thermal limits to be
temperature. The correlation analysis has shown that the copepods are
generally (although not always) responding to the recent thermal
environment. Shown below are thermal limits, body size, and fecundity
values plotted against the temperature at the time of collection. Also
shown is warming tolerance, calculated as the difference between upper
thermal limit and the collection temperature.
We generally see an increase in thermal limits with increasing
collection temperature, a slight decrease in body size, and variable
relationships between temperature and fecundity. All species maintained
some degree of buffer between environmental temperatures and upper
thermal limits, but Epischura and L. minutus
approached their upper thermal limits during the warmest collections
during the summer.
ctmax_temp = ggplot(full_data, aes(x = collection_temp, y = ctmax, colour = sp_name)) +
geom_smooth(method = "lm", linewidth = 3) +
geom_point(size = 3) +
labs(x = "Collection Temperature (°C)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
size_temp = ggplot(filter(full_data, sex != "juvenile"), aes(x = collection_temp, y = size, colour = sp_name)) +
geom_smooth(method = "lm", linewidth = 3) +
geom_point(size = 3) +
labs(x = "Collection Temperature (°C)",
y = "Length (mm)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
wt_temp = ggplot(full_data, aes(x = collection_temp, y = warming_tol, colour = sp_name)) +
geom_smooth(method = "lm", linewidth = 3) +
geom_point(size = 3) +
labs(x = "Collection Temperature (°C)",
y = "Warming Tolerance (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
eggs_temp = ggplot(full_data, aes(x = collection_temp, y = fecundity, colour = sp_name)) +
geom_smooth(method = "lm", linewidth = 3) +
geom_point(size = 3) +
labs(x = "Collection Temperature (°C)",
y = "Fecundity (# Eggs)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")
ggarrange(ctmax_temp, size_temp, wt_temp, eggs_temp,
common.legend = T, legend = "right")

full_data %>%
#filter(sex == "female") %>%
group_by(sp_name) %>% filter(n() > 5) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>%
ggplot(aes(x = collection_temp, y = ctmax, colour = sp_name)) +
facet_wrap(sp_name~.) +
geom_point(size = 2, alpha = 0.8) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
labs(x = "Collection Temp. (°C)",
y = "CTmax (°C)") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "none")

Copepods spent several days in lab during experiments. Shown below
are the CTmax residuals (taken from a model of CTmax against collection
temperature) plotted against the time spent in lab before measurements
were made. Individual regressions are shown for the residuals against
days in lab for each collection. We can see clearly that thermal limits
are fairly stable over time.
ggplot(ctmax_resids, aes(x = days_in_lab, y = resids, colour = sp_name, group = collection_date)) +
facet_wrap(sp_name~.) +
geom_point(size = 4, alpha = 0.5) +
geom_smooth(method = "lm", se = F, linewidth = 1) +
scale_x_continuous(breaks = c(0:5)) +
labs(x = "Days in lab",
y = "CTmax Residuals") +
scale_colour_manual(values = species_cols) +
theme_matt_facets() +
theme(legend.position = "none")

The term “acclimation response ratio” is often used to describe the
effect of temperature on thermal limits. The ARR is calculated as the
change in thermal limits per degree change in acclimation temperature.
For our data, we will estimate ARR as the slope of CTmax against
collection temperature. These slopes were taken from a regression of
CTmax against collection temperature and body size. Two different model
types were used, a simple linear regression and a mixed effects model.
The estimated ARR values were generally highly similar between the model
types used.
coef_model_data = full_data %>%
group_by(sp_name, sex) %>%
filter(n() > 5 & !str_detect(sp_name, pattern = "kindti"))
coef_n = full_data %>%
group_by(sp_name, sex) %>%
filter(n() > 5) %>%
summarise(sample_n = n(),
mean_ctmax = mean(ctmax))
ARR_vals = coef_model_data %>%
do(broom::tidy(lm(ctmax ~ collection_temp + size, data = .))) %>%
filter(term == "collection_temp") %>%
select(sp_name, sex, "ARR" = estimate, std.error) %>%
arrange(ARR) %>%
inner_join(coef_n, by = c("sp_name", "sex"))
ARR_vals %>%
select("Species" = sp_name,
"Group" = sex,
"N" = sample_n,
ARR,
"Error" = std.error) %>%
knitr::kable()
| Epischura lacustris |
juvenile |
18 |
-0.0001189 |
0.1057432 |
| Epischura lacustris |
male |
12 |
0.1828277 |
0.0511841 |
| Leptodiaptomus minutus |
female |
196 |
0.2102371 |
0.0169417 |
| Leptodiaptomus minutus |
male |
32 |
0.2184299 |
0.0292233 |
| Skistodiaptomus oregonensis |
female |
171 |
0.2414597 |
0.0239109 |
| Skistodiaptomus oregonensis |
male |
27 |
0.2611101 |
0.0480816 |
| Leptodiaptomus sicilis |
female |
67 |
0.3431587 |
0.0863374 |
| Skistodiaptomus oregonensis |
juvenile |
14 |
0.3813308 |
0.0971708 |
| Epischura lacustris |
female |
39 |
0.3966359 |
0.0548040 |
| Leptodiaptomus minutus |
juvenile |
9 |
0.5489301 |
0.0968203 |
| Leptodiaptomus sicilis |
male |
15 |
1.2828429 |
0.3075849 |
mle.model = lmer(data = model_data,
ctmax ~ collection_temp + size + sex + (size + collection_temp|sex:sp_name))
mle_coefs = coefficients(mle.model)$`sex:sp_name` %>%
mutate("group" = rownames(.)) %>%
select(group, "intercept" = "(Intercept)", "ARR" = collection_temp, size) %>%
separate(group, into = c("sex", "species"), sep = ":", remove = TRUE) %>%
remove_rownames()
mle_ARR = mle_coefs %>%
select(sp_name = species, sex, ARR) %>%
mutate("model" = "mixed effects") %>%
inner_join(coef_n, by = c("sp_name", "sex"))
ARR_comp = bind_rows(mle_ARR,
mutate(ARR_vals, "model" = "linear"))
ARR_comp %>%
filter(sp_name %in% c("Skistodiaptomus oregonensis", "Leptodiaptomus minutus", "Leptodiaptomus sicilis", "Epischura lacustris")) %>%
ggplot(aes(x = model, y = ARR, group = sp_name)) +
facet_grid(sp_name~sex) +
geom_point(size = 3) +
geom_line(linewidth = 1.5) +
scale_y_continuous(breaks = c(0, 0.5, 1)) +
theme_matt_facets() +
theme(axis.text.x = element_text(angle = 300, hjust = 0, vjust = 0.5))

coef_plot = mle_ARR %>%
mutate("abbr" = case_when(
sp_name == "Epischura lacustris" ~ "E. lac",
sp_name == "Leptodiaptomus minutus" ~ "L. min",
sp_name == "Skistodiaptomus oregonensis" ~ "S. ore",
sp_name == "Leptodiaptomus sicilis" ~ "L. sic"
)) %>%
ggplot(aes(x = abbr, y = ARR, colour = sp_name, shape = sex)) +
# geom_errorbar(aes(ymin = ARR - std.error, ymax = ARR + std.error),
# width = 0.35, linewidth = 1, position = position_dodge(width = 0.5)) +
geom_point(size = 5,
position = position_dodge(width = 0.5)) +
scale_colour_manual(values = species_cols) +
guides(colour = "none") +
labs(x = "Species",
y = "ARR",
shape = "Group") +
theme_matt() +
theme(legend.position = "right")
coef_lim_plot = ggplot(mle_ARR, aes(x = mean_ctmax, y = ARR)) +
geom_smooth(method = "lm", colour = "grey70", se = F, linewidth = 2) +
# geom_errorbar(aes(colour = sp_name, ymin = ARR - std.error, ymax = ARR + std.error),
# width = 0.5, linewidth = 1, position = position_dodge(width = 0.5)) +
geom_point(aes(colour = sp_name, shape = sex ),
size = 5,
position = position_dodge(width = 0.5)) +
scale_colour_manual(values = species_cols) +
guides(colour = "none") +
labs(x = "Mean CTmax (°C)",
y = "ARR",
shape = "Group") +
theme_matt() +
theme(legend.position = "right")
ggarrange(coef_plot, coef_lim_plot, common.legend = T, legend = "right")

Sex and stage variation in thermal limits
Previous sections have generally lumped juvenile, female, and male
individuals together. There may be important stage- or sex-specific
differences in CTmax though. For several species, we have measurements
for individuals in different stages or of different sexes.
sex_sample_sizes = ctmax_resids %>%
group_by(sp_name, sex) %>%
summarise(num = n()) %>%
pivot_wider(id_cols = sp_name,
names_from = sex,
values_from = num,
values_fill = 0) %>%
select("Species" = sp_name, "Juvenile" = juvenile, "Female" = female, "Male" = male)
knitr::kable(sex_sample_sizes, align = "c")
| Epischura lacustris |
18 |
39 |
12 |
| Leptodiaptomus minutus |
8 |
196 |
32 |
| Leptodiaptomus sicilis |
0 |
67 |
15 |
| Limnocalanus macrurus |
2 |
5 |
1 |
| Osphranticum labronectum |
0 |
1 |
0 |
| Senecella calanoides |
0 |
1 |
0 |
| Skistodiaptomus oregonensis |
14 |
170 |
27 |
The female-male and female-juvenile comparisons show that there are
generally no differences in thermal limits between these groups.
ctmax_resids %>%
filter(sp_name %in% filter(sex_sample_sizes, Male > 0, Female > 0)$Species &
sex != "juvenile") %>%
ggplot(aes(x = sex, y = resids, colour = sp_name, group = sp_name)) +
facet_wrap(sp_name~., ncol = 2) +
geom_smooth(method = "lm", se = F, linewidth = 1) +
geom_point(size = 3,
alpha = 0.5,
position = position_jitter(height = 0, width = 0.05)) +
labs(x = "Sex",
y = "CTmax Residuals") +
scale_colour_manual(values = species_cols) +
theme_bw(base_size = 18) +
theme(legend.position = "none",
panel.grid = element_blank())

ctmax_resids %>%
filter(sp_name %in% filter(sex_sample_sizes, Juvenile > 0 & Female > 0)$Species &
sex != "male") %>%
ggplot(aes(x = sex, y = resids, colour = sp_name, group = sp_name)) +
facet_wrap(sp_name~., ncol = 1) +
geom_smooth(method = "lm", se = F, linewidth = 1) +
geom_point(size = 3,
alpha = 0.5,
position = position_jitter(height = 0, width = 0.05)) +
labs(x = "Sex",
y = "CTmax (°C)") +
scale_colour_manual(values = species_cols) +
theme_bw(base_size = 18) +
theme(legend.position = "none",
panel.grid = element_blank())

Trait Correlations and Trade-offs
A relationship between size and upper thermal limits has been
suggested in a wide range of other taxa. Shown below are the measured
upper thermal limits plotted against prosome length. The overall
relationship (inclusive of all species) is shown as the black line in
the background. Regressions for each individual species are also shown.
For the three diaptomids and Epischura there is a slight
negative relationship between size and thermal limits. However, across
the entire assemblage, there is a slight increase in thermal limits with
increasing size. This may, however, be due to the relative
overrepresentation of larger summer species like
Skistodiaptomus. Increasing the measurements on larger,
cold-water species like L. sicilis and Limnocalanus
may alter this observed pattern.
full_data %>%
#filter(sex == "female") %>%
ggplot( aes(x = size, y = ctmax, colour = sp_name)) +
geom_smooth(data = full_data,
aes(x = size, y = ctmax),
method = "lm",
colour ="black",
linewidth = 2.5) +
geom_point(size = 2, alpha = 0.8) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

Shown here is the relationship for each species individually.
full_data %>%
#filter(sex == "female") %>%
group_by(sp_name) %>% filter(n() >2) %>% filter(!str_detect(sp_name, pattern = "kindti")) %>%
ggplot( aes(x = size, y = ctmax, colour = sp_name)) +
facet_wrap(sp_name~., scales = "free", nrow = 2) +
geom_point(size = 2, alpha = 0.8) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "none")

full_data %>%
group_by(sp_name, sex) %>%
summarize(mean_ctmax = mean(ctmax, na.rm = T),
mean_size = mean(size, na.rm = T)) %>%
#filter(sex == "female") %>%
ggplot(aes(x = mean_size, y = mean_ctmax)) +
geom_smooth(method = "lm", se = F, linewidth = 2, colour = "black") +
geom_point(aes(colour = sp_name, shape = sex),
size = 5) +
labs(x = "Length (mm)",
y = "CTmax (°C)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

Shown here is the relationship between fecundity and size, showing
the classic pattern of increasing egg production with increasing
size.
ctmax_resids %>%
drop_na(fecundity) %>%
ggplot(aes(x = size, y = fecundity, colour = sp_name)) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
geom_point(size = 2, alpha = 0.5) +
labs(x = "Prosome length (mm)",
y = "Fecundity (# Eggs)",
colour = "Species") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

Individuals may also allocate energy to different fitness related
traits, prioritizing reproductive output over environmental tolerance,
for example. Shown below is the relationship between CTmax residuals
(again, controlling for the effects of collection temperature) against
fecundity. We can see clearly that individuals with increased fecundity
are not decreasing thermal limits, suggesting that there is no energetic
trade-off between these traits.
ctmax_resids %>%
drop_na(fecundity) %>%
ggplot(aes(y = resids, x = fecundity, colour = sp_name)) +
geom_smooth(method = "lm", se = F, linewidth = 2) +
geom_point(size = 2, alpha = 0.5) +
labs(y = "CTmax (°C)",
x = "Fecundity (# Eggs)") +
scale_colour_manual(values = species_cols) +
theme_matt() +
theme(legend.position = "right")

if(predict_vuln == F){
knitr::knit_exit()
}
LS0tCnRpdGxlOiBTZWFzb25hbGl0eSBpbiBMYWtlIENoYW1wbGFpbiBDb3BlcG9kIFRoZXJtYWwgTGltaXRzCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgICAgICAgY29kZV9mb2xkaW5nOiBoaWRlCiAgICAgICAgICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgICAgICAgICB0b2M6IHRydWUKICAgICAgICAgIHRvY19mbG9hdDogdHJ1ZQogIGdpdGh1Yl9kb2N1bWVudDoKICAgICAgICAgIGh0bWxfcHJldmlldzogZmFsc2UKICAgICAgICAgIHRvYzogdHJ1ZQogICAgICAgICAgdG9jX2RlcHRoOiAzCi0tLQoKYGBge3IgdG8tZG99CiMjIyBUbyBEbyAKCiMgQWN0dWFsIHN0YXRpc3RpY3MgZm9yIHJlbGF0aW9uc2hpcHMgYmV0d2VlbiB0ZW1wZXJhdHVyZSBhbmQgQ1RtYXgsIHNpemUsIGFuZCBmZWN1bmRpdHkKIyBQdWxsIHJlc2lkdWFscyBmcm9tIENUbWF4IH4gdGVtcGVyYXR1cmUgbW9kZWwsIGFuZCBleGFtaW5lIHRoZSBjaGFuZ2Ugb3ZlciB0aW1lIGluIGxhYiBhbmQgdGhlIHJlbGF0aW9uc2hpcCB3aXRoIGZlY3VuZGl0eQoKYGBgCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9VCwgbWVzc2FnZSA9IEYsIHdhcm5pbmcgPSBGLCBlY2hvID0gRn0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGVjaG8gPSBrbml0cjo6aXNfaHRtbF9vdXRwdXQoKSwKICBmaWcuYWxpZ24gPSAiY2VudGVyIiwKICBmaWcucGF0aCA9ICIuLi9GaWd1cmVzL21hcmtkb3duLyIsCiAgZGV2ID0gYygicG5nIiwgInBkZiIpLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgY29sbGFwc2UgPSBUCikKCnRoZW1lX21hdHQgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgIGRhcmtfdGV4dCA9ICJncmV5MjAiKXsKICBtaWRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzJdCiAgbGlnaHRfdGV4dCA8LSAgbW9ub2Nocm9tZVI6OmdlbmVyYXRlX3BhbGV0dGUoZGFya190ZXh0LCAiZ29fbGlnaHRlciIsIG5fY29sb3VycyA9IDUpWzNdCiAgCiAgZ2dwdWJyOjp0aGVtZV9wdWJyKGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBtaWRfdGV4dCwgbGluZWhlaWdodCA9IDEuMSksCiAgICAgIHRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAxLjUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IGRhcmtfdGV4dCksCiAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gbWlkX3RleHQpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygzLCAwLCAwLCAwKSwgIm1tIikpLAogICAgICBheGlzLnRpdGxlLnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmdpbiA9IHVuaXQoYygwLCA1LCAwLCAwKSwgIm1tIiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemU9YmFzZV9zaXplICogMC45KSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUgKiAwLjksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjZSA9ICJib2xkIiksCiAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAuMjUsIDAuMjUsIDAuMjUsIDAuMjUsImNtIikKICAgICkKfQoKdGhlbWVfbWF0dF9mYWNldHMgPSBmdW5jdGlvbihiYXNlX3NpemUgPSAxOCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkYXJrX3RleHQgPSAiZ3JleTIwIil7CiAgbWlkX3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVsyXQogIGxpZ2h0X3RleHQgPC0gIG1vbm9jaHJvbWVSOjpnZW5lcmF0ZV9wYWxldHRlKGRhcmtfdGV4dCwgImdvX2xpZ2h0ZXIiLCBuX2NvbG91cnMgPSA1KVszXQogIAogIHRoZW1lX2J3KGJhc2VfZmFtaWx5PSJzYW5zIikgJStyZXBsYWNlJSAKICAgIHRoZW1lKAogICAgICBwYW5lbC5ncmlkID0gZWxlbWVudF9ibGFuaygpLAogICAgICBwYW5lbC5iYWNrZ3JvdW5kICA9IGVsZW1lbnRfcmVjdChmaWxsPSJ0cmFuc3BhcmVudCIsIGNvbG91cj1OQSksIAogICAgICBwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLCAKICAgICAgbGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoZmlsbD0idHJhbnNwYXJlbnQiLCBjb2xvdXI9TkEpLAogICAgICBsZWdlbmQua2V5ID0gZWxlbWVudF9yZWN0KGZpbGw9InRyYW5zcGFyZW50IiwgY29sb3VyPU5BKSwKICAgICAgdGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvdXIgPSBtaWRfdGV4dCwgbGluZWhlaWdodCA9IDEuMSksCiAgICAgIHN0cmlwLnRleHQueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplKSwKICAgICAgdGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDEuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3VyID0gZGFya190ZXh0KSwKICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSBiYXNlX3NpemUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXIgPSBtaWRfdGV4dCksCiAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDMsIDAsIDAsIDApLCAibW0iKSksCiAgICAgIGF4aXMudGl0bGUueSA9IGVsZW1lbnRfdGV4dChzaXplID0gYmFzZV9zaXplICogMS4yLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWFyZ2luID0gdW5pdChjKDAsIDUsIDAsIDApLCAibW0iKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZT1iYXNlX3NpemUgKiAwLjkpLAogICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IGJhc2Vfc2l6ZSAqIDAuOSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWNlID0gImJvbGQiKSwKICAgICAgcGxvdC5tYXJnaW4gPSBtYXJnaW4oMC4yNSwgMC4yNSwgMC4yNSwgMC4yNSwiY20iKQogICAgKQp9CgpzcGVjaWVzX2NvbHMgPSBjKCJMZXB0b2RpYXB0b211cyBtaW51dHVzIiA9ICIjZmZkMDI5IiwKICAgICAgICAgICAgICAgICAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyBqdXZlbmlsZSIgPSAiI2UzZDhhZiIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMgbWFsZSIgPSAiI2ZmZTg5NiIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiID0gIiNEODZGMjkiLAogICAgICAgICAgICAgICAgICJMZXB0b2RpYXB0b211cyBzaWNpbGlzIG1hbGUiID0gIiNFMjhDMDAiLAogICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiID0gIiNDNUMzNUEiLAogICAgICAgICAgICAgICAgICJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMgbWFsZSIgPSAiI2U2ZTZhYSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIGp1dmVuaWxlIiA9ICJwbHVtMSIsIAogICAgICAgICAgICAgICAgICJFcGlzY2h1cmEgbGFjdXN0cmlzIG1hbGUiID0gInBsdW0zIiwgCiAgICAgICAgICAgICAgICAgIkVwaXNjaHVyYSBsYWN1c3RyaXMiID0gInBsdW00IiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyIgPSAic2t5Ymx1ZTQiLCAKICAgICAgICAgICAgICAgICAiTGltbm9jYWxhbnVzIG1hY3J1cnVzIG1hbGUiID0gInNreWJsdWUzIiwgCiAgICAgICAgICAgICAgICAgIkxpbW5vY2FsYW51cyBtYWNydXJ1cyBqdXZlbmlsZSIgPSAic2t5Ymx1ZSIsIAogICAgICAgICAgICAgICAgICJTZW5lY2VsbGEgY2FsYW5vaWRlcyIgPSAiZGFya3NlYWdyZWVuMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkgbWFsZSIgPSAibGlnaHRibHVlMyIsCiAgICAgICAgICAgICAgICAgIkxlcHRvZG9yYSBraW5kdGkiID0gImxpZ2h0Ymx1ZTQiLAogICAgICAgICAgICAgICAgICJMZXB0b2RvcmEga2luZHRpIGp1dmVuaWxlIiA9ICJsaWdodGJsdWUiLAogICAgICAgICAgICAgICAgICJPc3BocmFudGljdW0gbGFicm9uZWN0dW0iID0gImxpZ2h0Y29yYWwiKQpgYGAKCiMjIENvcGVwb2QgQ29sbGVjdGlvbgoKQ29wZXBvZHMgd2VyZSBjb2xsZWN0ZWQgYXQgYXBwcm94aW1hdGVseSB3ZWVrbHkgaW50ZXJ2YWxzIGZyb20gTGFrZSBDaGFtcGxhaW4gKEJ1cmxpbmd0b24gRmlzaGluZyBQaWVyKS4gUGxhbmt0b24gd2FzIGNvbGxlY3RlZCBmcm9tIHRoZSB0b3AgMyBtZXRlcnMgdXNpbmcgYSAyNTAgdW0gbWVzaCBuZXQuIAoKYGBge3J9CiMgTGFrZSBDaGFtcGxhaW4gbmVhciBCdXJsaW5ndG9uLCBWVApzaXRlTnVtYmVyID0gIjA0Mjk0NTAwIgpDaGFtcGxhaW5JbmZvID0gcmVhZE5XSVNzaXRlKHNpdGVOdW1iZXIpCnBhcmFtZXRlckNkID0gIjAwMDEwIgpzdGFydERhdGUgPSAiMjAyMy0wMS0wMSIKZW5kRGF0ZSA9ICIiCiNzdGF0Q2QgPSBjKCIwMDAwMSIsICIwMDAwMiIsIjAwMDAzIiwgIjAwMDExIikgIyAxIC0gbWF4LCAyIC0gbWluLCAzID0gbWVhbgoKIyBDb25zdHJ1Y3RzIHRoZSBVUkwgZm9yIHRoZSBkYXRhIHdhbnRlZCB0aGVuIGRvd25sb2FkcyB0aGUgZGF0YQp1cmwgPSBjb25zdHJ1Y3ROV0lTVVJMKHNpdGVOdW1iZXJzID0gc2l0ZU51bWJlciwgcGFyYW1ldGVyQ2QgPSBwYXJhbWV0ZXJDZCwgCiAgICAgICAgICAgICAgICAgICAgICAgc3RhcnREYXRlID0gc3RhcnREYXRlLCBlbmREYXRlID0gZW5kRGF0ZSwgc2VydmljZSA9ICJ1diIpCgp0ZW1wX2RhdGEgPSBpbXBvcnRXYXRlck1MMSh1cmwsIGFzRGF0ZVRpbWUgPSBUKSAlPiUgCiAgbXV0YXRlKCJkYXRlIiA9IGFzLkRhdGUoZGF0ZVRpbWUpKSAlPiUgCiAgc2VsZWN0KGRhdGUsICJ0ZW1wIiA9IFhfMDAwMTBfMDAwMDApCmBgYAoKQ29sbGVjdGlvbnMgYmVnYW4gaW4gbGF0ZSBNYXkgMjAyMy4gU2V2ZXJhbCBnYXBzIGFyZSBwcmVzZW50LCBidXQgY29sbGVjdGlvbnMgaGF2ZSBjb250aW51ZWQgYXQgcm91Z2hseSB3ZWVrbHkgaW50ZXJ2YWxzIHNpbmNlIHRoZW4uIENvcGVwb2RzIGZyb20gYHIgbGVuZ3RoKHVuaXF1ZShmdWxsX2RhdGEkY29sbGVjdGlvbl9kYXRlKSlgIGNvbGxlY3Rpb25zIHdlcmUgdXNlZCB0byBtYWtlIGEgdG90YWwgb2YgYHIgZGltKGZ1bGxfZGF0YSlbMV1gIHRoZXJtYWwgbGltaXQgbWVhc3VyZW1lbnRzLiBPdmVyIHRoaXMgdGltZSBwZXJpb2QsIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmVzIHJhbmdlZCBmcm9tIGByIHBhc3RlKG1pbihmdWxsX2RhdGEkY29sbGVjdGlvbl90ZW1wKSwgIiB0byAiLCBtYXgoZnVsbF9kYXRhJGNvbGxlY3Rpb25fdGVtcCksIHNlcCA9ICIiKWDCsEMuICAgICAKClRoZXJlIGlzIHN1YnN0YW50aWFsIHZhcmlhdGlvbiBpbiB0aGVybWFsIGxpbWl0cyBhY3Jvc3MgdGhlIHNwZWNpZXMgY29sbGVjdGVkLiBUaGVyZSBpcyBhbHNvIHNvbWUgZGVncmVlIG9mIHZhcmlhdGlvbiB3aXRoaW4gdGhlIHNwZWNpZXMsIHdpdGggdGhlcm1hbCBsaW1pdHMgaW5jcmVhc2luZyBzbGlnaHRseSBkdXJpbmcgdGhlIHN1bW1lci4gICAgCgpgYGB7ciBjdG1heC10aW1lc2VyaWVzLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KIyMgRGFpbHkgdmFsdWVzIGZvciB0aGUgcGVyaW9kIGV4YW1pbmVkIGJ5IGRhdGFzZXQKY29sbGVjdGlvbl9jb25kaXRpb25zID0gdGVtcF9kYXRhICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXApLAogICAgICAgICAgICBtZWRfdGVtcCA9IG1lZGlhbih0ZW1wKSwKICAgICAgICAgICAgdmFyX3RlbXAgPSB2YXIodGVtcCksIAogICAgICAgICAgICBtaW5fdGVtcCA9IG1pbih0ZW1wKSwgCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXApKSAlPiUgCiAgbXV0YXRlKCJyYW5nZV90ZW1wIiA9IG1heF90ZW1wIC0gbWluX3RlbXAsCiAgICAgICAgIGRhdGUgPSBhcy5EYXRlKGRhdGUpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAgCiAgZmlsdGVyKGRhdGUgPj0gKG1pbihhcy5EYXRlKGZ1bGxfZGF0YSRjb2xsZWN0aW9uX2RhdGUpKSAtIDcpKQoKIyMgTWVhbiBmZW1hbGUgdGhlcm1hbCBsaW1pdHMgZm9yIGVhY2ggc3BlY2llcywgZ3JvdXBlZCBieSBjb2xsZWN0aW9uCnNwZWNpZXNfc3VtbWFyaWVzID0gZnVsbF9kYXRhICU+JSAgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBzdW1tYXJpc2UoIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJzYW1wbGVfc2l6ZSIgPSBuKCksCiAgICAgICAgICAgICJjdG1heF9zdF9lcnIiID0gKHNkKGN0bWF4KSAvIHNxcnQoc2FtcGxlX3NpemUpKSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLCAKICAgICAgICAgICAgIm1lYW5fc2l6ZSIgPSBtZWFuKHNpemUpLAogICAgICAgICAgICAic2l6ZV9zdF9lcnIiID0gKHNkKHNpemUpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAic2l6ZV92YXIiID0gdmFyKHNpemUpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgYXJyYW5nZShkZXNjKHNhbXBsZV9zaXplKSkKCmFkdWx0X3N1bW1hcmllcyA9IGZ1bGxfZGF0YSAlPiUgIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBncm91cF9ieShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBzdW1tYXJpc2UoIm1lYW5fY3RtYXgiID0gbWVhbihjdG1heCksCiAgICAgICAgICAgICJzYW1wbGVfc2l6ZSIgPSBuKCksCiAgICAgICAgICAgICJjdG1heF9zdF9lcnIiID0gKHNkKGN0bWF4KSAvIHNxcnQoc2FtcGxlX3NpemUpKSwKICAgICAgICAgICAgImN0bWF4X3ZhciIgPSB2YXIoY3RtYXgpLCAKICAgICAgICAgICAgIm1lYW5fc2l6ZSIgPSBtZWFuKHNpemUpLAogICAgICAgICAgICAic2l6ZV9zdF9lcnIiID0gKHNkKHNpemUpIC8gc3FydChzYW1wbGVfc2l6ZSkpLAogICAgICAgICAgICAic2l6ZV92YXIiID0gdmFyKHNpemUpKSAlPiUgIAogIHVuZ3JvdXAoKSAlPiUgCiAgY29tcGxldGUoc3BfbmFtZSwgY29sbGVjdGlvbl9kYXRlKSAlPiUgCiAgYXJyYW5nZShkZXNjKHNhbXBsZV9zaXplKSkKCgpnZ3Bsb3QoKSArIAogIGdlb21fdmxpbmUoZGF0YSA9IHVuaXF1ZShzZWxlY3QoZnVsbF9kYXRhLCBjb2xsZWN0aW9uX2RhdGUpKSwgCiAgICAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSksCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleTkwIiwKICAgICAgICAgICAgIGxpbmV3aWR0aCA9IDEpICsgCiAgZ2VvbV9saW5lKGRhdGEgPSBjb2xsZWN0aW9uX2NvbmRpdGlvbnMsIAogICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoZGF0ZSksIHkgPSBtZWFuX3RlbXApLAogICAgICAgICAgICBjb2xvdXIgPSAiYmxhY2siLCAKICAgICAgICAgICAgbGluZXdpZHRoID0gMikgKyAKICAjIGdlb21fZXJyb3JiYXIoZGF0YSA9IHNwZWNpZXNfc3VtbWFyaWVzLAogICMgICAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwKICAjICAgICAgICAgICAgICAgICAgIHltaW4gPSBtZWFuX2N0bWF4IC0gY3RtYXhfc3RfZXJyLCB5bWF4ID0gbWVhbl9jdG1heCArIGN0bWF4X3N0X2VyciwKICAjICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHNwX25hbWUpLAogICMgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksCiAgIyAgICAgICAgICAgICAgIHdpZHRoID0gNSwgbGluZXdpZHRoID0gMSkgKwogIGdlb21fcG9pbnQoZGF0YSA9IGFkdWx0X3N1bW1hcmllcywgCiAgICAgICAgICAgICBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IG1lYW5fY3RtYXgsIGNvbG91ciA9IHNwX25hbWUsIHNpemUgPSBzYW1wbGVfc2l6ZSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkRhdGUiLCAKICAgICAgIHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIiwKICAgICAgIHNpemUgPSAiU2FtcGxlIFNpemUiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKU2l6ZSBhbHNvIHZhcmllZCBib3RoIGJldHdlZW4gYW5kIHdpdGhpbiBzcGVjaWVzLiAKCmBgYHtyIHNpemUtdGltZXNlcmllcywgZmlnLndpZHRoPTEwLCBmaWcuaGVpZ2h0PTV9CmdncGxvdCgpICsgCiAgZ2VvbV92bGluZShkYXRhID0gdW5pcXVlKHNlbGVjdChmdWxsX2RhdGEsIGNvbGxlY3Rpb25fZGF0ZSkpLCAKICAgICAgICAgICAgIGFlcyh4aW50ZXJjZXB0ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpKSwKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5OTAiLAogICAgICAgICAgICAgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX2xpbmUoZGF0YSA9IGNvbGxlY3Rpb25fY29uZGl0aW9ucywgCiAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShkYXRlKSwgeSA9IG1lYW5fdGVtcCksCiAgICAgICAgICAgIGNvbG91ciA9ICJibGFjayIsIAogICAgICAgICAgICBsaW5ld2lkdGggPSAyKSArIAogICMgZ2VvbV9lcnJvcmJhcihkYXRhID0gc3BlY2llc19zdW1tYXJpZXMsCiAgIyAgICAgICAgICAgICAgIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCAKICAjICAgICAgICAgICAgICAgICAgIHltaW4gPSBtZWFuX2N0bWF4IC0gY3RtYXhfc3RfZXJyLCB5bWF4ID0gbWVhbl9jdG1heCArIGN0bWF4X3N0X2VyciwKICAjICAgICAgICAgICAgICAgICAgIGNvbG91ciA9IHNwX25hbWUpLAogICMgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMSksCiAgIyAgICAgICAgICAgICAgIHdpZHRoID0gNSwgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KGRhdGEgPSBhZHVsdF9zdW1tYXJpZXMsIAogICAgICAgICAgICAgYWVzKHggPSBhcy5EYXRlKGNvbGxlY3Rpb25fZGF0ZSksIHkgPSBtZWFuX3NpemUgKiA0MCwgY29sb3VyID0gc3BfbmFtZSwgc2l6ZSA9IHNhbXBsZV9zaXplKSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAxKSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBzY2FsZV95X2NvbnRpbnVvdXMoCiAgICBuYW1lID0gIlRlbXBlcmF0dXJlIiwgIyBGZWF0dXJlcyBvZiB0aGUgZmlyc3QgYXhpcwogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyh+Li80MCwgbmFtZT0iUHJvc29tZSBMZW5ndGggKG1tKSIpLCAjIEFkZCBhIHNlY29uZCBheGlzIGFuZCBzcGVjaWZ5IGl0cyBmZWF0dXJlcwogICAgYnJlYWtzID0gYygwLDUsMTAsMTUsMjAsMjUsMzApCiAgKSArIAogIGxhYnMoeCA9ICJEYXRlIiwgCiAgICAgICB5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpGb3IgdGhlIHRocmVlIHNwZWNpZXMgd2l0aCB0aGUgbW9zdCBkYXRhICgqU2tpc3RvZGlhcHRvbXVzKiwgKkwuIG1pbnV0dXMqLCAqRXBpc2NodXJhKiksIHNob3duIGJlbG93IGlzIENUbWF4IGFuZCBib2R5IHNpemUsIHBsb3R0ZWQgYWdhaW5zdCB0aGUgZGF5IG9mIHRoZSB5ZWFyIGZvciBlYWNoIHNleC9zdGFnZSBzZXBhcmF0ZWx5LiAKCmBgYHtyIHRyYWl0LWRveS1mZWF0dXJlLCBmaWcud2lkdGggPSAxNCwgZmlnLmhlaWdodCA9IDd9CmN0bWF4X2ZlYXR1cmUgPSBmdWxsX2RhdGEgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBjKCJTa2lzdG9kaWFwdG9tdXMgb3JlZ29uZW5zaXMiLCAiTGVwdG9kaWFwdG9tdXMgbWludXR1cyIsIkVwaXNjaHVyYSBsYWN1c3RyaXMiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF9ncmlkKHNwX25hbWV+c2V4KSArIAogIGdlb21fcG9pbnQoKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgdGhlIFllYXIiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiKSArIAogIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKCnNpemVfZmVhdHVyZSA9IGZ1bGxfZGF0YSAlPiUgIAogIG11dGF0ZShkb3kgPSB5ZGF5KGNvbGxlY3Rpb25fZGF0ZSkpICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAlaW4lIGMoIlNraXN0b2RpYXB0b211cyBvcmVnb25lbnNpcyIsICJMZXB0b2RpYXB0b211cyBtaW51dHVzIiwgIkVwaXNjaHVyYSBsYWN1c3RyaXMiKSkgJT4lIAogIGdncGxvdChhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IHNpemUsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGZhY2V0X2dyaWQoc3BfbmFtZX5zZXgpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkRheSBvZiB0aGUgWWVhciIsIAogICAgICAgeSA9ICJTaXplIChtbSkiKSArIAogIGd1aWRlcyhjb2xvciA9IEZBTFNFKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkgKwogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMzAwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKCmdnYXJyYW5nZShjdG1heF9mZWF0dXJlLCBzaXplX2ZlYXR1cmUsIGNvbW1vbi5sZWdlbmQgPSBULCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgoKIyMgVGVtcGVyYXR1cmUgVmFyaWFiaWxpdHkKTGFrZSBDaGFtcGxhaW4gaXMgaGlnaGx5IHNlYXNvbmFsLCB3aXRoIGJvdGggYXZlcmFnZSB0ZW1wZXJhdHVyZXMgYW5kIHRlbXBlcmF0dXJlIHZhcmlhYmlsaXR5IGNoYW5naW5nIHRocm91Z2hvdXQgdGhlIHllYXIuIFRoZXNlIHBhdHRlcm5zIGluIHRoZSBleHBlcmllbmNlZCB0aGVybWFsIGVudmlyb25tZW50IG1heSBkcml2ZSB0aGUgb2JzZXJ2ZWQgdmFyaWF0aW9uIGluIGNvcGVwb2QgdGhlcm1hbCBsaW1pdHMuIEhvd2V2ZXIsIHRoZSB0aW1lIHBlcmlvZCBhZmZlY3RpbmcgY29wZXBvZCB0aGVybWFsIGxpbWl0cyBpcyB1bmtub3duLiBEZXBlbmRpbmcgdGhlIG9uIHRoZSBkdXJhdGlvbiBvZiB0aW1lIGNvbnNpZGVyZWQsIHRoZXJlIGFyZSBsYXJnZSBjaGFuZ2VzIGluIHRoZSBleHBlcmllbmNlZCBlbnZpcm9ubWVudCwgaW4gcGFydGljdWxhciByZWdhcmRpbmcgdGhlIHRlbXBlcmF0dXJlIHJhbmdlIGFuZCB2YXJpYW5jZS4gQ29uc2lkZXIgZm9yIGV4YW1wbGUgdGhyZWUgdGltZSBwZXJpb2RzOiB0aGUgZGF5IG9mIGNvbGxlY3Rpb24sIG9uZSB3ZWVrIHByaW9yIHRvIGNvbGxlY3Rpb24sIGFuZCBmb3VyIHdlZWtzIHByaW9yIHRvIGNvbGxlY3Rpb24uIFdoaWxlIHRoZSBvdmVyYWxsIHBhdHRlcm4gaXMgc2ltaWxhciwgd2UgY2FuIHNlZSB0aGF0LCB1bnN1cnByaXNpbmdseSwgY29uc2lkZXJpbmcgbG9uZ2VyIHBlcmlvZHMgb2YgdGltZSByZXN1bHRzIGluIGxhcmdlciByYW5nZXMgYW5kIHNsaWdodGx5IGNoYW5nZXMgdGhlIHBhdHRlcm4gb2YgdmFyaWFuY2UgZXhwZXJpZW5jZWQuIAoKYGBge3IgZGFpbHktdGVtcC1kYXRhfQojIyBEYWlseSB2YWx1ZXMKZGFpbHlfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JQogIHVuZ3JvdXAoKSAlPiUgCiAgZ3JvdXBfYnkoZGF0ZSkgJT4lIAogIHN1bW1hcmlzZShtZWFuX3RlbXAgPSBtZWFuKHRlbXApLAogICAgICAgICAgICBtZWRfdGVtcCA9IG1lZGlhbih0ZW1wKSwKICAgICAgICAgICAgdmFyX3RlbXAgPSB2YXIodGVtcCksIAogICAgICAgICAgICBtaW5fdGVtcCA9IG1pbih0ZW1wKSwgCiAgICAgICAgICAgIG1heF90ZW1wID0gbWF4KHRlbXApKSAlPiUgCiAgbXV0YXRlKCJyYW5nZV90ZW1wIiA9IG1heF90ZW1wIC0gbWluX3RlbXApCgpkYXlfcHJpb3JfdGVtcF9kYXRhID0gdGVtcF9kYXRhICU+JSAKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZShkYXRlID0gZGF0ZSArIDEpICU+JSAKICByZW5hbWVfd2l0aCguZm4gPSB+IHBhc3RlMCgicHJpb3JfZGF5XyIsIC54KSwgLmNvbHMgPSBjKC1kYXRlKSkKCmRhaWx5X3Bsb3QgPSBkYWlseV90ZW1wX2RhdGEgJT4lIAogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBkYXRlLCB5ID0gdGVtcCwgY29sb3VyID0gcGFyYW1ldGVyKSkgKyAKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwgIAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKyAKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKICBnZ3RpdGxlKCJEYWlseSBWYWx1ZXMiKSArIAogIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiAgICAgICB4ID0gIiIpICsgCiAgdGhlbWVfYncoYmFzZV9zaXplID0gMjApICsgCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoKYGBge3IgcHJlZGljdG9ycy1mdW5jdGlvbn0KIyMgRGVmaW5pbmcgdGhlIGZ1bmN0aW9uIHRvIGdldCBwcmVkaWN0b3IgdmFsdWVzIGZvciBwZXJpb2RzIG9mIGRpZmZlcmVudCBsZW5ndGhzCmdldF9wcmVkaWN0b3JzID0gZnVuY3Rpb24oZGFpbHlfdmFsdWVzLCByYXdfdGVtcCwgbl9kYXlzKXsKICBwcmVmaXggPSBzdHJfcmVwbGFjZV9hbGwoeGZ1bjo6bnVtYmVyc190b193b3JkcyhuX2RheXMpLCBwYXR0ZXJuID0gIiAiLCByZXBsYWNlbWVudCA9ICItIikKICAKICBtZWFuX3ZhbHVlcyA9IGRhaWx5X3ZhbHVlcyAlPiUgCiAgICB1bmdyb3VwKCkgJT4lIAogICAgbXV0YXRlKG1lYW5fbWF4ID0gc2xpZGVfdmVjKC54ID0gbWF4X3RlbXAsIC5mID0gbWVhbiwgLmJlZm9yZSA9IG5fZGF5cywgLmNvbXBsZXRlID0gVCksCiAgICAgICAgICAgbWVhbl9taW4gPSBzbGlkZV92ZWMoLnggPSBtaW5fdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSwKICAgICAgICAgICBtZWFuX3JhbmdlID0gc2xpZGVfdmVjKC54ID0gcmFuZ2VfdGVtcCwgLmYgPSBtZWFuLCAuYmVmb3JlID0gbl9kYXlzLCAuY29tcGxldGUgPSBUKSkgJT4lIAogICAgc2VsZWN0KGRhdGUsIG1lYW5fbWF4LCBtZWFuX21pbiwgbWVhbl9yYW5nZSkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpCiAgCiAgcGVyaW9kX3ZhbHVlcyA9IHJhd190ZW1wICU+JSAKICAgIG11dGF0ZShtZWFuID0gc2xpZGVfaW5kZXhfbWVhbih0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYV9ybSA9IFQpLAogICAgICAgICAgIG1heCA9IHNsaWRlX2luZGV4X21heCh0ZW1wLCBpID0gZGF0ZSwgYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtaW4gPSBzbGlkZV9pbmRleF9taW4odGVtcCwgaSA9IGRhdGUsIGJlZm9yZSA9IGRheXMobl9kYXlzKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBUKSwKICAgICAgICAgICBtZWQgPSBzbGlkZV9pbmRleF9kYmwodGVtcCwgLmkgPSBkYXRlLCAuYmVmb3JlID0gZGF5cyhuX2RheXMpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFfcm0gPSBULCAuZiA9IG1lZGlhbiksCiAgICAgICAgICAgdmFyID0gc2xpZGVfaW5kZXhfZGJsKHRlbXAsIC5pID0gZGF0ZSwgLmJlZm9yZSA9IGRheXMobl9kYXlzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5mID0gdmFyKSwKICAgICAgICAgICByYW5nZSA9IG1heCAtIG1pbikgJT4lICAKICAgIHNlbGVjdCgtdGVtcCkgJT4lICAKICAgIGRpc3RpbmN0KCkgJT4lIAogICAgcmVuYW1lX3dpdGgoIH4gcGFzdGUocHJlZml4LCAiZGF5IiwgLngsIHNlcCA9ICJfIiksIC5jb2xzID0gYygtZGF0ZSkpJT4lIAogICAgaW5uZXJfam9pbihtZWFuX3ZhbHVlcywgYnkgPSBjKCJkYXRlIikpICU+JSAgCiAgICBkcm9wX25hKCkKICAKICByZXR1cm4ocGVyaW9kX3ZhbHVlcykKfQpgYGAKCmBgYHtyIHByZWRpY3RvcnMtYW5kLXBsb3RzLCBmaWcud2lkdGg9MTIsIGZpZy5oZWlnaHQ9NX0KIyAjIyBHZXR0aW5nIHByZWRpY3RvciB2YXJpYWJsZXMgZm9yIGRpZmZlcmVudCBwZXJpb2RzCiMgCiMgIyMjIFNob3J0ICh0aHJlZSBkYXlzKQojIHRocmVlX2RheV90ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmF3X3RlbXAgPSB0ZW1wX2RhdGEsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDMpCiMgCiMgIyMjIE9ORSBXRUVLCndlZWtfdGVtcHMgPSBnZXRfcHJlZGljdG9ycyhkYWlseV92YWx1ZXMgPSBkYWlseV90ZW1wX2RhdGEsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDcpCgp3ZWVrX3Bsb3QgPSB3ZWVrX3RlbXBzICU+JQogIHBpdm90X2xvbmdlcihjb2xzID0gYygtZGF0ZSksCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lCiAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoInNldmVuX2RheV9tZWFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9tYXgiLAogICAgICAgICAgICAgICAgICAgICAgICAgICJzZXZlbl9kYXlfbWluIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAic2V2ZW5fZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInNldmVuX2RheV9yYW5nZSIpKSAlPiUKICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsKICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKwogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKICAgICJtZWFuX3RlbXAiID0gIm9saXZlZHJhYjMiLAogICAgIm1lZF90ZW1wIiA9ICJzZWFncmVlbjMiLAogICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLAogICAgIm1pbl90ZW1wIiA9ICJkb2RnZXJibHVlIiwKICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKICAgICJ2YXJfdGVtcCIgPSAiZGFya2dvbGRlbnJvZDEiCiAgKSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBhcy5EYXRlKGMoIjIwMjMtMDEtMDEiLCAiMjAyMy0wNC0wMSIsICIyMDIzLTA3LTAxIikpKSArCiAgZ2d0aXRsZSgiT25lIFdlZWsiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIFRXTyBXRUVLUwojIHR3b193ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5fZGF5cyA9IDE0KQojIAojIHR3b193ZWVrX3Bsb3QgPSB0d29fd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZvdXJ0ZWVuX2RheV9tZWFuIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWVkIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmb3VydGVlbl9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZm91cnRlZW5fZGF5X21pbiIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV92YXIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZvdXJ0ZWVuX2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIlR3byBXZWVrcyIpICsgCiMgICBsYWJzKHkgPSAiVGVtcGVyYXR1cmUgKMKwQykiLAojICAgICAgICB4ID0gIiIpICsgCiMgICB0aGVtZV9idyhiYXNlX3NpemUgPSAyMCkgKyAKIyAgIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEZPVVIgV0VFS1MKZm91cl93ZWVrX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gMjgpCgpmb3VyX3dlZWtfcGxvdCA9IGZvdXJfd2Vla190ZW1wcyAlPiUKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJwYXJhbWV0ZXIiLAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAidGVtcCIpICU+JQogIGZpbHRlcihwYXJhbWV0ZXIgJWluJSBjKCJ0d2VudHktZWlnaHRfZGF5X21lYW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X21lZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfbWF4IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAidHdlbnR5LWVpZ2h0X2RheV9taW4iLAogICAgICAgICAgICAgICAgICAgICAgICAgICJ0d2VudHktZWlnaHRfZGF5X3ZhciIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgInR3ZW50eS1laWdodF9kYXlfcmFuZ2UiKSkgJT4lCiAgbXV0YXRlKHBhcmFtZXRlciA9IHBhc3RlKHdvcmQocGFyYW1ldGVyLCBzdGFydCA9IDMsIHNlcCA9IGZpeGVkKCJfIikpLCAiX3RlbXAiLCBzZXAgPSAiIikpICU+JQogIGdncGxvdChhZXMoeCA9IGRhdGUsIHkgPSB0ZW1wLCBjb2xvdXIgPSBwYXJhbWV0ZXIpKSArCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoCiAgICAibWVhbl90ZW1wIiA9ICJvbGl2ZWRyYWIzIiwKICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKICAgICJtYXhfdGVtcCIgPSAidG9tYXRvIiwKICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiAgICAicmFuZ2VfdGVtcCIgPSAiZ29sZGVucm9kMyIsCiAgICAidmFyX3RlbXAiID0gImRhcmtnb2xkZW5yb2QxIgogICkpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKwogIGdndGl0bGUoIkZvdXIgV2Vla3MiKSArCiAgbGFicyh5ID0gIlRlbXBlcmF0dXJlICjCsEMpIiwKICAgICAgIHggPSAiIikgKwogIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArCiAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDI3MCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCiMgCiMgCiMgIyMjIEVJR0hUIFdFRUtTCiMgZWlnaHRfd2Vla190ZW1wcyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGRhaWx5X3RlbXBfZGF0YSwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJhd190ZW1wID0gdGVtcF9kYXRhLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gNTYpCiMgCiMgZWlnaHRfd2Vla19wbG90ID0gZWlnaHRfd2Vla190ZW1wcyAlPiUgCiMgICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUpLAojICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInBhcmFtZXRlciIsIAojICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ0ZW1wIikgJT4lIAojICAgZmlsdGVyKHBhcmFtZXRlciAlaW4lIGMoImZpZnR5LXNpeF9kYXlfbWVhbiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9tZWQiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgImZpZnR5LXNpeF9kYXlfbWF4IiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9taW4iLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICJmaWZ0eS1zaXhfZGF5X3ZhciIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAiZmlmdHktc2l4X2RheV9yYW5nZSIpKSAlPiUgCiMgICBtdXRhdGUocGFyYW1ldGVyID0gcGFzdGUod29yZChwYXJhbWV0ZXIsIHN0YXJ0ID0gMywgc2VwID0gZml4ZWQoIl8iKSksICJfdGVtcCIsIHNlcCA9ICIiKSkgJT4lIAojICAgZ2dwbG90KGFlcyh4ID0gZGF0ZSwgeSA9IHRlbXAsIGNvbG91ciA9IHBhcmFtZXRlcikpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMSkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gYygKIyAgICAgIm1lYW5fdGVtcCIgPSAib2xpdmVkcmFiMyIsCiMgICAgICJtZWRfdGVtcCIgPSAic2VhZ3JlZW4zIiwKIyAgICAgIm1heF90ZW1wIiA9ICJ0b21hdG8iLCAgCiMgICAgICJtaW5fdGVtcCIgPSAiZG9kZ2VyYmx1ZSIsCiMgICAgICJyYW5nZV90ZW1wIiA9ICJnb2xkZW5yb2QzIiwKIyAgICAgInZhcl90ZW1wIiA9ICJkYXJrZ29sZGVucm9kMSIKIyAgICkpICsgCiMgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYXMuRGF0ZShjKCIyMDIzLTAxLTAxIiwgIjIwMjMtMDQtMDEiLCAiMjAyMy0wNy0wMSIpKSkgKyAKIyAgIGdndGl0bGUoIkVpZ2h0IFdlZWtzIikgKyAKIyAgIGxhYnMoeSA9ICJUZW1wZXJhdHVyZSAowrBDKSIsCiMgICAgICAgIHggPSAiIikgKyAKIyAgIHRoZW1lX2J3KGJhc2Vfc2l6ZSA9IDIwKSArIAojICAgdGhlbWUocGFuZWwuZ3JpZCA9IGVsZW1lbnRfYmxhbmsoKSwKIyAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gMjcwLCBoanVzdCA9IDAsIHZqdXN0ID0gMC41KSkKIyAKZ2dhcnJhbmdlKGRhaWx5X3Bsb3QsIHdlZWtfcGxvdCwgZm91cl93ZWVrX3Bsb3QsIAogICAgICAgICAgY29tbW9uLmxlZ2VuZCA9IFQsIG5yb3cgPSAxLCBsZWdlbmQgPSAiYm90dG9tIikKYGBgCgpUaGUgZGlmZmVyZW50IHRpbWUgcGVyaW9kcyBleGFtaW5lZCBieSB0aGlzIGNsaW1hdGUgZGF0YSBoaWdobGlnaHRzIHRoYXQgdGhlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGNoYW5nZXMgYmFzZWQgb24gdGhlIHdpbmRvdyBleGFtaW5lZC4gRm9yIGV4YW1wbGUsIG1pbmltdW0gYW5kIG1heGltdW0gdGVtcGVyYXR1cmVzIGV4cGVyaWVuY2VkIG92ZXIgd2Vla2x5IGludGVydmFscyBhcmUgY2xvc2VseSBsaW5rZWQsIHdoZXJlYXMgdGhlcmUgaXMgYSBkaXN0aW5jdCBzZWFzb25hbCBjeWNsZSBpbiB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gbWluaW11bSBhbmQgbWF4aW11bSB0ZW1wZXJhdHVyZXMgZXhwZXJpZW5jZWQgb3ZlciBwZXJpb2RzIG9mIGZvdXIgd2Vla3MuIAoKYGBge3J9Cm9uZV93ZWVrX2RveV9kYXRhID0gd2Vla190ZW1wcyAlPiUgCiAgbXV0YXRlKGRveSA9IHlkYXkoZGF0ZSkpCgpvbmVfd2Vla190ZW1wX2NpcmNsZSA9IGdncGxvdChvbmVfd2Vla19kb3lfZGF0YSwgYWVzKHggPSBzZXZlbl9kYXlfbWVhbl9tYXgsIHkgPSBzZXZlbl9kYXlfbWVhbl9taW4sIGNvbG91ciA9IGRveSkpICsgCiAgZ2VvbV9wb2ludCgpICsgCiAgc2NhbGVfY29sb3VyX2dyYWRpZW50MigKICAgIGhpZ2ggPSAiZG9kZ2VyYmx1ZTQiLAogICAgbWlkID0gImNvcmFsMiIsCiAgICBsb3cgPSAiZG9kZ2VyYmx1ZTQiLAogICAgICBtaWRwb2ludCA9IDE4Mi41KSArIAogIGxhYnMoeCA9ICJNYXguIFRlbXAuICjCsEMpIiwKICAgICAgIHkgPSAiTWluLiBUZW1wLiAowrBDKSIpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNaW4uIFRlbXAuICjCsEMpIikgKyAKICBnZ3RpdGxlKCJPbmUgV2VlayIpICsgCiAgdGhlbWVfbWF0dCgpCgpmb3VyX3dlZWtfZG95X2RhdGEgPSBmb3VyX3dlZWtfdGVtcHMgJT4lIAogIG11dGF0ZShkb3kgPSB5ZGF5KGRhdGUpKQoKZm91cl93ZWVrX3RlbXBfY2lyY2xlID0gZ2dwbG90KGZvdXJfd2Vla19kb3lfZGF0YSwgYWVzKHggPSBgdHdlbnR5LWVpZ2h0X2RheV9tYXhgLCB5ID0gYHR3ZW50eS1laWdodF9kYXlfbWluYCwgY29sb3VyID0gZG95KSkgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgaGlnaCA9ICJkb2RnZXJibHVlNCIsCiAgICBtaWQgPSAiY29yYWwyIiwKICAgIGxvdyA9ICJkb2RnZXJibHVlNCIsCiAgICAgIG1pZHBvaW50ID0gMTgyLjUpICsgCiAgbGFicyh4ID0gIk1heC4gVGVtcC4gKMKwQykiLAogICAgICAgeSA9ICJNaW4uIFRlbXAuICjCsEMpIikgKyAKICBnZ3RpdGxlKCJGb3VyIFdlZWsiKSArIAogIHRoZW1lX21hdHQoKQoKZ2dhcnJhbmdlKG9uZV93ZWVrX3RlbXBfY2lyY2xlLCBmb3VyX3dlZWtfdGVtcF9jaXJjbGUsCiAgICAgICAgICBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gImJvdHRvbSIpCmBgYAoKVGhlIHRoZXJtYWwgZW52aXJvbm1lbnQgb3ZlciBhbnkgcGVyaW9kIG9mIHRpbWUgbWF5IGRyaXZlIHBhdHRlcm5zIGluIHRoZXJtYWwgYWNjbGltYXRpb24uIFRvIGV4cGxvcmUgdGhlIHBvdGVudGlhbCBlZmZlY3RzIG9mIGRpZmZlcmVudCBhY2NsaW1hdGlvbiB3aW5kb3dzLCB3ZSBleGFtaW5lZCB0aGUgY29ycmVsYXRpb24gYmV0d2VlbiB0aGVybWFsIGxpbWl0cyBhbmQgZGlmZmVyZW50IHJlcHJlc2VudGF0aW9ucyBvZiB0aGUgdGhlcm1hbCBlbnZpcm9ubWVudCBmb3IgZGlmZmVyZW50IHBlcmlvZHMgb2YgdGltZS4gU2hvd24gYmVsb3cgYXJlIHRoZSBjb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgZm9yIHRoZXNlIHJlbGF0aW9uc2hpcHMuIEVhY2ggZmFjZXQgc2hvd3MgdGhlIHJlbGF0aW9uc2hpcCBmb3IgYSBkaWZmZXJlbnQgZGltZW5zaW9uIG9mIHRoZSB0aGVybWFsIGVudmlyb25tZW50LiBDb3JyZWxhdGlvbiBjb2VmZmljaWVudHMgYXJlIHBsb3R0ZWQgZm9yIGRpZmZlcmVudCBkdXJhdGlvbnMsIGZvciBzcGVjaWVzIHRoYXQgd2VyZSBjb2xsZWN0ZWQgbW9yZSB0aGFuIGZpdmUgdGltZXMuIE9ubHkgZGF0YSBmb3IgbWF0dXJlIGZlbWFsZSBjb3BlcG9kcyB3YXMgaW5jbHVkZWQuIAoKV2UgY2FuIHNlZSB0aGF0LCBpbiBnZW5lcmFsLCBjb3BlcG9kcyBhcmUgcmVzcG9uZGluZyB0byBwcm94aW1hdGUgY3VlcyBmcm9tIHRoZSB0aGVybWFsIGVudmlyb25tZW50LCB3aXRoIGNvcnJlbGF0aW9ucyBnZW5lcmFsbHkgZHJvcHBpbmcgb2ZmIHN1YnN0YW50aWFsbHkgYXMgYWNjbGltYXRpb24gd2luZG93IGR1cmF0aW9uIGluY3JlYXNlcy4gQW4gZXhjZXB0aW9uIGlzICpFcGlzY2h1cmEgbGFjdXN0cmlzKiwgd2hpY2ggYXBwZWFycyB0byBiZSByZXNwb25kaW5nIHRvIG1heGltdW0gdGVtcGVyYXR1cmVzIGV4cGVyaWVuY2VkIG92ZXIgYSAyMCBkYXkgdGltZSBwZXJpb2QuIAoKYGBge3J9CiMjIyBQdWxsaW5nIHByZWRpY3RvcnMgYW5kIG1lYXN1cmluZyBjb3JyZWxhdGlvbnMgZm9yIG11Y2ggZmluZXIgdGltZXNjYWxlczsgMS01NiBkYXlzCgp3b3Jkc190b19udW1iZXJzIDwtIGZ1bmN0aW9uKHMpIHsKICBzIDwtIHN0cmluZ3I6OnN0cl90b19sb3dlcihzKQogIGZvciAoaSBpbiAwOjU2KQogICAgcyA8LSBzdHJpbmdyOjpzdHJfcmVwbGFjZV9hbGwocywgd29yZHMoaSksIGFzLmNoYXJhY3RlcihpKSkKICBzCn0KCm51bV9jb2xscyA9IGZ1bGxfZGF0YSAlPiUgCiAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIHNlbGVjdChjb2xsZWN0aW9uX2RhdGUsIHNwX25hbWUpICU+JSAgCiAgZGlzdGluY3QoKSAlPiUgIAogIGNvdW50KHNwX25hbWUpICU+JSAKICBmaWx0ZXIobiA+PSA1KQoKY29ycl92YWxzID0gZGF0YS5mcmFtZSgpCgpkdXJfdmFscyA9IGMoMTo1MCkKZm9yKGkgaW4gZHVyX3ZhbHMpewogIAogIGR1cmF0aW9uX3RlbXBzID0gZ2V0X3ByZWRpY3RvcnMoZGFpbHlfdmFsdWVzID0gZGFpbHlfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IHRlbXBfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbl9kYXlzID0gaSkgJT4lIAogICAgZmlsdGVyKGRhdGUgJWluJSBhc19kYXRlKHVuaXF1ZShmdWxsX2RhdGEkY29sbGVjdGlvbl9kYXRlKSkpCiAgCiAgY29ycl9kYXRhID0gZnVsbF9kYXRhICU+JQogICAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAogICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAogICAgaW5uZXJfam9pbihkdXJhdGlvbl90ZW1wcywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAKICAgIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb2xsZWN0aW9uX3RlbXAsIGNvbnRhaW5zKCJkYXlfIikpLAogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJ2YWx1ZSIsIAogICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gInByZWRpY3RvciIpICU+JSAgCiAgICBncm91cF9ieShzcF9uYW1lLCBwcmVkaWN0b3IpICU+JSAKICAgIHN1bW1hcmlzZShjb3JyZWxhdGlvbiA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkZXN0aW1hdGUsCiAgICAgICAgICAgICAgcC52YWx1ZSA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkcC52YWx1ZSwKICAgICAgICAgICAgICBjaV9sb3cgPSBjb3IudGVzdChjdG1heCwgdmFsdWUpJGNvbmYuaW50WzFdLAogICAgICAgICAgICAgIGNpX2hpZ2ggPSBjb3IudGVzdChjdG1heCwgdmFsdWUpJGNvbmYuaW50WzJdKSAlPiUgCiAgICBmaWx0ZXIocHJlZGljdG9yICE9ICJjb2xsZWN0aW9uX3RlbXAiKSAlPiUgCiAgICBtdXRhdGUoc2lnID0gaWZlbHNlKHAudmFsdWUgPDAuMDUsICJTaWcuIiwgIk5vbiBTaWcuIikpICU+JSAKICAgIHNlcGFyYXRlKHByZWRpY3RvciwgIl9kYXlfIiwgaW50byA9IGMoTkEsICJwYXJhbWV0ZXIiKSkgJT4lIAogICAgbXV0YXRlKGR1cmF0aW9uID0gaSkKICAKICBjb3JyX3ZhbHMgPSBiaW5kX3Jvd3MoY29ycl92YWxzLCBjb3JyX2RhdGEpCn0KCmNvbGxfY29yciA9IGZ1bGxfZGF0YSAlPiUKICAgIGZpbHRlcihzcF9uYW1lICVpbiUgbnVtX2NvbGxzJHNwX25hbWUpICU+JSAKICAgIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICAgIGdyb3VwX2J5KHNwX25hbWUpICU+JSAKICAgIHN1bW1hcmlzZShjb3JyZWxhdGlvbiA9IGNvci50ZXN0KGN0bWF4LCBjb2xsZWN0aW9uX3RlbXApJGVzdGltYXRlLAogICAgICAgICAgICAgIHAudmFsdWUgPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRwLnZhbHVlLAogICAgICAgICAgICAgIGNpX2xvdyA9IGNvci50ZXN0KGN0bWF4LCBjb2xsZWN0aW9uX3RlbXApJGNvbmYuaW50WzFdLAogICAgICAgICAgICAgIGNpX2hpZ2ggPSBjb3IudGVzdChjdG1heCwgY29sbGVjdGlvbl90ZW1wKSRjb25mLmludFsyXSkgJT4lIAogICAgbXV0YXRlKHNpZyA9IGlmZWxzZShwLnZhbHVlIDwwLjA1LCAiU2lnLiIsICJOb24gU2lnLiIpKSAlPiUgCiAgICBtdXRhdGUoZHVyYXRpb24gPSAwLAogICAgICAgICAgIHBhcmFtZXRlciA9ICJjb2xsX3RlbXAiKQoKY29ycl92YWxzID0gY29ycl92YWxzICU+JSAgCiAgbXV0YXRlKGR1cmF0aW9uID0gYXMubnVtZXJpYyhkdXJhdGlvbikpICU+JSAKICBiaW5kX3Jvd3MoY29sbF9jb3JyKQpgYGAKCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD02fQpjb3JyX3ZhbHMgJT4lIAptdXRhdGUocGFyYW1ldGVyID0gZmN0X3JlbGV2ZWwocGFyYW1ldGVyLCBjKCJtaW4iLCAibWF4IiwgInJhbmdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbiIsICJtZWQiLCAidmFyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAibWVhbl9taW4iLCAibWVhbl9tYXgiLCAibWVhbl9yYW5nZSIpKSkgJT4lIApnZ3Bsb3QoYWVzKHggPSBkdXJhdGlvbiwgeSA9IGNvcnJlbGF0aW9uLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKC5+cGFyYW1ldGVyKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9saW5lKGxpbmV3aWR0aCA9IDEpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgbGFicyh4ID0gIkR1cmF0aW9uIChkYXlzKSIsCiAgICAgICB5ID0gIkNvcnJlbGF0aW9uIiwgCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKQpgYGAKClNob3duIGhlcmUgYXJlIHRoZSB0b3AgdGhyZWUgZmFjdG9ycyBmb3IgZWFjaCBzcGVjaWVzLiAKCmBgYHtyIHByZWRpY3Rvci1jb3JyZWxhdGlvbnN9CiMgCiMgY29ycl92YWxzID0gZnVsbF9kYXRhICU+JQojICAgZmlsdGVyKHNwX25hbWUgJWluJSBudW1fY29sbHMkc3BfbmFtZSkgJT4lIAojICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAojICAgbXV0YXRlKGNvbGxlY3Rpb25fZGF0ZSA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSkgJT4lIAojICAgZnVsbF9qb2luKHRlbXBfcHJlZGljdG9ycywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAKIyAgIHBpdm90X2xvbmdlcihjb2xzID0gYyhjb2xsZWN0aW9uX3RlbXAsIG1lYW5fdGVtcDp0YWlsKG5hbWVzKC4pLCAxKSksCiMgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gInZhbHVlIiwgCiMgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAicHJlZGljdG9yIikgJT4lICAKIyAgIGdyb3VwX2J5KHNwX25hbWUsIHByZWRpY3RvcikgJT4lIAojICAgc3VtbWFyaXNlKGNvcnJlbGF0aW9uID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRlc3RpbWF0ZSwKIyAgICAgICAgICAgICBwLnZhbHVlID0gY29yLnRlc3QoY3RtYXgsIHZhbHVlKSRwLnZhbHVlLAojICAgICAgICAgICAgIGNpX2xvdyA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMV0sCiMgICAgICAgICAgICAgY2lfaGlnaCA9IGNvci50ZXN0KGN0bWF4LCB2YWx1ZSkkY29uZi5pbnRbMl0pICU+JSAKIyAgIG11dGF0ZShzaWcgPSBpZmVsc2UocC52YWx1ZSA8MC4wNSwgIlNpZy4iLCAiTm9uIFNpZy4iKSkKCmNvcnJfdmFscyAlPiUgIAogIGZpbHRlcihzaWcgPT0gIlNpZy4iKSAlPiUgCiAgZHJvcF9uYShjb3JyZWxhdGlvbikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JQogIGFycmFuZ2UoZGVzYyhjb3JyZWxhdGlvbikpICU+JSAKICBzbGljZV9oZWFkKG4gPSAzKSAlPiUgCiAgc2VsZWN0KCJTcGVjaWVzIiA9IHNwX25hbWUsICJQcmVkaWN0b3IiID0gcGFyYW1ldGVyLCAiRHVyYXRpb24iID0gZHVyYXRpb24sICJDb3JyZWxhdGlvbiIgPSBjb3JyZWxhdGlvbiwgIlAtVmFsdWUiID0gcC52YWx1ZSkgJT4lIAogIGtuaXRyOjprYWJsZShhbGlnbiA9ICJjIikKYGBgCgojIyBUcmFpdCBWYXJpYXRpb24gCmBgYHtyIGN0bWF4LWFuZC1zaXplLXN1bS1wbG90LCBmaWcud2lkdGg9MjAsIGZpZy5oZWlnaHQ9NX0KIyBjdG1heF9wbG90ID0gZnVsbF9kYXRhICU+JSAKIyAgIG11dGF0ZSggI3NwX25hbWUgPSBzdHJfcmVwbGFjZShzcF9uYW1lLCBwYXR0ZXJuID0gIiAiLAojICAgICAjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiXG4iKSwKIyAgICAgc3BfbmFtZSA9IGZjdF9yZW9yZGVyKHNwX25hbWUsIGN0bWF4LCBtZWFuKSkgJT4lIAojICAgZ2dwbG90KGFlcyh5ID0gc3BfbmFtZSwgeCA9IGN0bWF4KSkgKyAKIyAgIGdlb21fcG9pbnQoYWVzKGNvbG91cj0gc3BfbmFtZV9zdWIpLAojICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC4zKSwKIyAgICAgICAgICAgICAgc2l6ZSA9IDQpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHhsYWIoTlVMTCkgKyAKIyAgIGxhYnMoeSA9ICIiLAojICAgICAgICB4ID0gIkNUbWF4ICjCsEMpIiwKIyAgICAgICAgY29sb3VyID0gIkdyb3VwIikgKyAKIyAgIHRoZW1lX21hdHQoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIAojIHNpemVfcGxvdCA9IGZ1bGxfZGF0YSAlPiUgCiMgICBtdXRhdGUoc3BfbmFtZSA9IGZjdF9yZW9yZGVyKHNwX25hbWUsIGN0bWF4LCBtZWFuKSkgJT4lIAojICAgZ2dwbG90KGFlcyh5ID0gc3BfbmFtZSwgeCA9IHNpemUpKSArIAojICAgZ2VvbV9wb2ludChhZXMoY29sb3VyPSBzcF9uYW1lX3N1YiksCiMgICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjMpLAojICAgICAgICAgICAgICBzaXplID0gNCkgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAojICAgbGFicyh4ID0gIlByb3NvbWUgTGVuZ3RoIChtbSkiLAojICAgICAgICB5ID0gIiIsIAojICAgICAgICBjb2xvdXIgPSAiR3JvdXAiKSArIAojICAgZ3VpZGVzKGNvbG9yID0gZ3VpZGVfbGVnZW5kKG5jb2wgPSAxKSkgKwojICAgdGhlbWVfbWF0dChiYXNlX3NpemUgPSApICsgCiMgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLAojICAgICAgICAgYXhpcy50ZXh0LnkgPSBlbGVtZW50X2JsYW5rKCksCiMgICAgICAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwLCJjbSIpKQojIAojIHRyYWl0X3Bsb3QgPSBjdG1heF9wbG90ICsgc2l6ZV9wbG90CiMgdHJhaXRfcGxvdApgYGAKClNob3duIGJlbG93IGFyZSB0aGUgY2x1dGNoIHNpemUgZGlzdHJpYnV0aW9ucyBmb3IgdGhlIHRocmVlIGRpYXB0b21paWQgc3BlY2llcywgd2hpY2ggcHJvZHVjZSBlZ2cgc2FjcyB0aGF0IGFsbG93IGZvciBlYXN5IHF1YW50aWZpY2F0aW9uIG9mIGZlY3VuZGl0eS4gCgpgYGB7ciBmZWN1bmRpdHktaGlzdG9ncmFtLCBmaWcud2lkdGg9NywgZmlnLmhlaWdodD0xMH0KZnVsbF9kYXRhICU+JSAgCiAgZHJvcF9uYShmZWN1bmRpdHkpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gZmVjdW5kaXR5LCBmaWxsID0gc3BfbmFtZV9zdWIpKSArIAogIGZhY2V0X3dyYXAoLn5zcF9uYW1lX3N1YiwgbmNvbCA9IDEpICsgCiAgZ2VvbV9oaXN0b2dyYW0oYmlud2lkdGggPSAyKSArIAogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICBsYWJzKHggPSAiRmVjdW5kaXR5ICgjIEVnZ3MpIikgKwogIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpCmBgYAoKT25lIG9mIHRoZSBtYWluIGFpbXMgb2YgdGhpcyBwcm9qZWN0IGlzIHRvIGV4YW1pbmUgdGhlIHBhdHRlcm5zIGFuZCBwcm9jZXNzZXMgZHJpdmluZyB2YXJpYXRpb24gaW4gdXBwZXIgdGhlcm1hbCBsaW1pdHMgYWNyb3NzIHRoZXNlIHNwZWNpZXMgb2YgY29wZXBvZHMuIAoKIyMjIFZhcmlhdGlvbiB3aXRoIHRlbXBlcmF0dXJlIAoKV2UgZXhwZWN0IG9uZSBvZiB0aGUgcHJpbWFyeSBkcml2ZXJzIG9mIGNvcGVwb2QgdGhlcm1hbCBsaW1pdHMgdG8gYmUgdGVtcGVyYXR1cmUuIFRoZSBjb3JyZWxhdGlvbiBhbmFseXNpcyBoYXMgc2hvd24gdGhhdCB0aGUgY29wZXBvZHMgYXJlIGdlbmVyYWxseSAoYWx0aG91Z2ggbm90IGFsd2F5cykgcmVzcG9uZGluZyB0byB0aGUgcmVjZW50IHRoZXJtYWwgZW52aXJvbm1lbnQuIFNob3duIGJlbG93IGFyZSB0aGVybWFsIGxpbWl0cywgYm9keSBzaXplLCBhbmQgZmVjdW5kaXR5IHZhbHVlcyBwbG90dGVkIGFnYWluc3QgdGhlIHRlbXBlcmF0dXJlIGF0IHRoZSB0aW1lIG9mIGNvbGxlY3Rpb24uIEFsc28gc2hvd24gaXMgd2FybWluZyB0b2xlcmFuY2UsIGNhbGN1bGF0ZWQgYXMgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB1cHBlciB0aGVybWFsIGxpbWl0IGFuZCB0aGUgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gCgpXZSBnZW5lcmFsbHkgc2VlIGFuIGluY3JlYXNlIGluIHRoZXJtYWwgbGltaXRzIHdpdGggaW5jcmVhc2luZyBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlLCBhIHNsaWdodCBkZWNyZWFzZSBpbiBib2R5IHNpemUsIGFuZCB2YXJpYWJsZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdGVtcGVyYXR1cmUgYW5kIGZlY3VuZGl0eS4gQWxsIHNwZWNpZXMgbWFpbnRhaW5lZCBzb21lIGRlZ3JlZSBvZiBidWZmZXIgYmV0d2VlbiBlbnZpcm9ubWVudGFsIHRlbXBlcmF0dXJlcyBhbmQgdXBwZXIgdGhlcm1hbCBsaW1pdHMsIGJ1dCAqRXBpc2NodXJhKiBhbmQgKkwuIG1pbnV0dXMqIGFwcHJvYWNoZWQgdGhlaXIgdXBwZXIgdGhlcm1hbCBsaW1pdHMgZHVyaW5nIHRoZSB3YXJtZXN0IGNvbGxlY3Rpb25zIGR1cmluZyB0aGUgc3VtbWVyLiAKCmBgYHtyIHRyYWl0LWNvbGwtdGVtcC1wbG90cywgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQpjdG1heF90ZW1wID0gZ2dwbG90KGZ1bGxfZGF0YSwgYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heCwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMykgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgpzaXplX3RlbXAgPSBnZ3Bsb3QoZmlsdGVyKGZ1bGxfZGF0YSwgc2V4ICE9ICJqdXZlbmlsZSIpLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHNpemUsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGxpbmV3aWR0aCA9IDMpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXBlcmF0dXJlICjCsEMpIiwgCiAgICAgICB5ID0gIkxlbmd0aCAobW0pIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCnd0X3RlbXAgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IHdhcm1pbmdfdG9sLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBsaW5ld2lkdGggPSAzKSArCiAgZ2VvbV9wb2ludChzaXplID0gMykgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wZXJhdHVyZSAowrBDKSIsIAogICAgICAgeSA9ICJXYXJtaW5nIFRvbGVyYW5jZSAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCgplZ2dzX3RlbXAgPSBnZ3Bsb3QoZnVsbF9kYXRhLCBhZXMoeCA9IGNvbGxlY3Rpb25fdGVtcCwgeSA9IGZlY3VuZGl0eSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgbGluZXdpZHRoID0gMykgKwogIGdlb21fcG9pbnQoc2l6ZSA9IDMpICsgCiAgbGFicyh4ID0gIkNvbGxlY3Rpb24gVGVtcGVyYXR1cmUgKMKwQykiLCAKICAgICAgIHkgPSAiRmVjdW5kaXR5ICgjIEVnZ3MpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKCmdnYXJyYW5nZShjdG1heF90ZW1wLCBzaXplX3RlbXAsIHd0X3RlbXAsIGVnZ3NfdGVtcCwgCiAgICAgICAgICBjb21tb24ubGVnZW5kID0gVCwgbGVnZW5kID0gInJpZ2h0IikKYGBgCgpgYGB7ciBmaWcud2lkdGg9NywgZmlnLmhlaWdodD01fQpmdWxsX2RhdGEgJT4lIAogICNmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JSBmaWx0ZXIobigpID4gNSkgJT4lIGZpbHRlcighc3RyX2RldGVjdChzcF9uYW1lLCBwYXR0ZXJuID0gImtpbmR0aSIpKSAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gY29sbGVjdGlvbl90ZW1wLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC44KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQpgYGAKCmBgYHtyIGN0bWF4LXJhbmdlLXBsb3QsIGluY2x1ZGUgPSBGfQpmdWxsX2RhdGEgJT4lICAKICBncm91cF9ieShzcF9uYW1lLCBjb2xsZWN0aW9uX2RhdGUsIGNvbGxlY3Rpb25fdGVtcCkgJT4lICAKICBzdW1tYXJpc2UoImN0bWF4X3JhbmdlIiA9IG1heChjdG1heCkgLSBtaW4oY3RtYXgpKSAlPiUgCiAgdW5ncm91cCgpICU+JSAKICBncm91cF9ieShzcF9uYW1lKSAlPiUgCiAgZmlsdGVyKG4oKSA+IDUpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBjb2xsZWN0aW9uX3RlbXAsIHkgPSBjdG1heF9yYW5nZSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIikgKyAKICBnZW9tX3BvaW50KCkgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpCmBgYAoKCmBgYHtyIGN0bWF4LWNvbGwtdGVtcC1tb2RlbCwgaW5jbHVkZSA9IEZ9CiMgYWR1bHRfZGF0YSA9IGZ1bGxfZGF0YSAlPiUgCiMgICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKQptb2RlbF9kYXRhID0gZnVsbF9kYXRhICU+JSAgCiAgZHJvcF9uYShzaXplLCBjdG1heCkKCmN0bWF4X3RlbXAubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKiBzcF9uYW1lKQpzaXplX3RlbXAubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgc2l6ZSB+IGNvbGxlY3Rpb25fdGVtcCAqIHNwX25hbWUgKQoKa25pdHI6OmthYmxlKGNhcjo6QW5vdmEoY3RtYXhfdGVtcC5tb2RlbCkpCgpjdG1heF9yZXNpZHMgPSBjYmluZChtb2RlbF9kYXRhLCAicmVzaWRzIiA9IGN0bWF4X3RlbXAubW9kZWwkcmVzaWR1YWxzLCAic2l6ZV9yZXNpZHMiID0gc2l6ZV90ZW1wLm1vZGVsJHJlc2lkdWFscykKCmBgYAoKQ29wZXBvZHMgc3BlbnQgc2V2ZXJhbCBkYXlzIGluIGxhYiBkdXJpbmcgZXhwZXJpbWVudHMuIFNob3duIGJlbG93IGFyZSB0aGUgQ1RtYXggcmVzaWR1YWxzICh0YWtlbiBmcm9tIGEgbW9kZWwgb2YgQ1RtYXggYWdhaW5zdCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlKSBwbG90dGVkIGFnYWluc3QgdGhlIHRpbWUgc3BlbnQgaW4gbGFiIGJlZm9yZSBtZWFzdXJlbWVudHMgd2VyZSBtYWRlLiBJbmRpdmlkdWFsIHJlZ3Jlc3Npb25zIGFyZSBzaG93biBmb3IgdGhlIHJlc2lkdWFscyBhZ2FpbnN0IGRheXMgaW4gbGFiIGZvciBlYWNoIGNvbGxlY3Rpb24uIFdlIGNhbiBzZWUgY2xlYXJseSB0aGF0IHRoZXJtYWwgbGltaXRzIGFyZSBmYWlybHkgc3RhYmxlIG92ZXIgdGltZS4gCgpgYGB7ciBjdG1heC10aW1lLWluLWxhYiwgZmlnLndpZHRoPTE1LCBmaWcuaGVpZ2h0PTEwfQpnZ3Bsb3QoY3RtYXhfcmVzaWRzLCBhZXMoeCA9IGRheXNfaW5fbGFiLCB5ID0gcmVzaWRzLCBjb2xvdXIgPSBzcF9uYW1lLCBncm91cCA9IGNvbGxlY3Rpb25fZGF0ZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4pICsgCiAgZ2VvbV9wb2ludChzaXplID0gNCwgYWxwaGEgPSAwLjUpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAxKSArIAogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDA6NSkpICsgCiAgbGFicyh4ID0gIkRheXMgaW4gbGFiIiwgCiAgICAgICB5ID0gIkNUbWF4IFJlc2lkdWFscyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpUaGUgdGVybSAiYWNjbGltYXRpb24gcmVzcG9uc2UgcmF0aW8iIGlzIG9mdGVuIHVzZWQgdG8gZGVzY3JpYmUgdGhlIGVmZmVjdCBvZiB0ZW1wZXJhdHVyZSBvbiB0aGVybWFsIGxpbWl0cy4gVGhlIEFSUiBpcyBjYWxjdWxhdGVkIGFzIHRoZSBjaGFuZ2UgaW4gdGhlcm1hbCBsaW1pdHMgcGVyIGRlZ3JlZSBjaGFuZ2UgaW4gYWNjbGltYXRpb24gdGVtcGVyYXR1cmUuIEZvciBvdXIgZGF0YSwgd2Ugd2lsbCBlc3RpbWF0ZSBBUlIgYXMgdGhlIHNsb3BlIG9mIENUbWF4IGFnYWluc3QgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZS4gVGhlc2Ugc2xvcGVzIHdlcmUgdGFrZW4gZnJvbSBhIHJlZ3Jlc3Npb24gb2YgQ1RtYXggYWdhaW5zdCBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlIGFuZCBib2R5IHNpemUuIFR3byBkaWZmZXJlbnQgbW9kZWwgdHlwZXMgd2VyZSB1c2VkLCBhIHNpbXBsZSBsaW5lYXIgcmVncmVzc2lvbiBhbmQgYSBtaXhlZCBlZmZlY3RzIG1vZGVsLiBUaGUgZXN0aW1hdGVkIEFSUiB2YWx1ZXMgd2VyZSBnZW5lcmFsbHkgaGlnaGx5IHNpbWlsYXIgYmV0d2VlbiB0aGUgbW9kZWwgdHlwZXMgdXNlZC4KCmBgYHtyIGFyci1jb21wLXBsb3QsIGZpZy53aWR0aD04LCBmaWcuaGVpZ2h0PTEwfQpjb2VmX21vZGVsX2RhdGEgPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIHNleCkgJT4lIAogIGZpbHRlcihuKCkgPiA1ICYgIXN0cl9kZXRlY3Qoc3BfbmFtZSwgcGF0dGVybiA9ICJraW5kdGkiKSkgCgpjb2VmX24gPSBmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIHNleCkgJT4lIAogIGZpbHRlcihuKCkgPiA1KSAlPiUgCiAgc3VtbWFyaXNlKHNhbXBsZV9uID0gbigpLCAKICAgICAgICAgICAgbWVhbl9jdG1heCA9IG1lYW4oY3RtYXgpKQoKQVJSX3ZhbHMgPSBjb2VmX21vZGVsX2RhdGEgJT4lIAogIGRvKGJyb29tOjp0aWR5KGxtKGN0bWF4IH4gY29sbGVjdGlvbl90ZW1wICsgc2l6ZSwgZGF0YSA9IC4pKSkgJT4lIAogIGZpbHRlcih0ZXJtID09ICJjb2xsZWN0aW9uX3RlbXAiKSAlPiUgCiAgc2VsZWN0KHNwX25hbWUsIHNleCwgIkFSUiIgPSBlc3RpbWF0ZSwgc3RkLmVycm9yKSAlPiUgCiAgYXJyYW5nZShBUlIpICU+JSAKICBpbm5lcl9qb2luKGNvZWZfbiwgYnkgPSBjKCJzcF9uYW1lIiwgInNleCIpKQogIApBUlJfdmFscyAlPiUgCiAgc2VsZWN0KCJTcGVjaWVzIiA9IHNwX25hbWUsIAogICAgICAgICAiR3JvdXAiID0gc2V4LCAKICAgICAgICAgIk4iID0gc2FtcGxlX24sCiAgICAgICAgIEFSUiwgCiAgICAgICAgICJFcnJvciIgPSBzdGQuZXJyb3IpICU+JSAKICBrbml0cjo6a2FibGUoKQoKbWxlLm1vZGVsID0gbG1lcihkYXRhID0gbW9kZWxfZGF0YSwKICAgICBjdG1heCB+IGNvbGxlY3Rpb25fdGVtcCArIHNpemUgKyBzZXggKyAoc2l6ZSArIGNvbGxlY3Rpb25fdGVtcHxzZXg6c3BfbmFtZSkpCgptbGVfY29lZnMgPSBjb2VmZmljaWVudHMobWxlLm1vZGVsKSRgc2V4OnNwX25hbWVgICU+JSAKICBtdXRhdGUoImdyb3VwIiA9IHJvd25hbWVzKC4pKSAlPiUgCiAgc2VsZWN0KGdyb3VwLCAiaW50ZXJjZXB0IiA9ICIoSW50ZXJjZXB0KSIsICJBUlIiID0gY29sbGVjdGlvbl90ZW1wLCBzaXplKSAlPiUgCiAgc2VwYXJhdGUoZ3JvdXAsIGludG8gPSBjKCJzZXgiLCAic3BlY2llcyIpLCBzZXAgPSAiOiIsIHJlbW92ZSA9IFRSVUUpICU+JSAKICByZW1vdmVfcm93bmFtZXMoKQoKbWxlX0FSUiA9IG1sZV9jb2VmcyAlPiUgIAogIHNlbGVjdChzcF9uYW1lID0gc3BlY2llcywgc2V4LCBBUlIpICU+JSAKICBtdXRhdGUoIm1vZGVsIiA9ICJtaXhlZCBlZmZlY3RzIikgICU+JSAKICBpbm5lcl9qb2luKGNvZWZfbiwgYnkgPSBjKCJzcF9uYW1lIiwgInNleCIpKQoKQVJSX2NvbXAgPSBiaW5kX3Jvd3MobWxlX0FSUiwgCiAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShBUlJfdmFscywgIm1vZGVsIiA9ICJsaW5lYXIiKSkKCkFSUl9jb21wICU+JSAKICBmaWx0ZXIoc3BfbmFtZSAlaW4lIGMoIlNraXN0b2RpYXB0b211cyBvcmVnb25lbnNpcyIsICJMZXB0b2RpYXB0b211cyBtaW51dHVzIiwgIkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMiLCAiRXBpc2NodXJhIGxhY3VzdHJpcyIpKSAlPiUgCmdncGxvdChhZXMoeCA9IG1vZGVsLCB5ID0gQVJSLCBncm91cCA9IHNwX25hbWUpKSArIAogIGZhY2V0X2dyaWQoc3BfbmFtZX5zZXgpICsKICBnZW9tX3BvaW50KHNpemUgPSAzKSArIAogIGdlb21fbGluZShsaW5ld2lkdGggPSAxLjUpICsgCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IGMoMCwgMC41LCAxKSkgKyAKICB0aGVtZV9tYXR0X2ZhY2V0cygpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSAzMDAsIGhqdXN0ID0gMCwgdmp1c3QgPSAwLjUpKQoKYGBgCgpgYGB7ciBjb2VmLXN1bW1hcnksIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD01fQpjb2VmX3Bsb3QgPSBtbGVfQVJSICU+JSAKICBtdXRhdGUoImFiYnIiID0gY2FzZV93aGVuKAogICAgc3BfbmFtZSA9PSAiRXBpc2NodXJhIGxhY3VzdHJpcyIgfiAiRS4gbGFjIiwKICAgIHNwX25hbWUgPT0gIkxlcHRvZGlhcHRvbXVzIG1pbnV0dXMiIH4gIkwuIG1pbiIsIAogICAgc3BfbmFtZSA9PSAiU2tpc3RvZGlhcHRvbXVzIG9yZWdvbmVuc2lzIiB+ICJTLiBvcmUiLAogICAgc3BfbmFtZSA9PSAiTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyIgfiAiTC4gc2ljIgogICkpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBhYmJyLCB5ID0gQVJSLCBjb2xvdXIgPSBzcF9uYW1lLCBzaGFwZSA9IHNleCkpICsgCiAgIyBnZW9tX2Vycm9yYmFyKGFlcyh5bWluID0gQVJSIC0gc3RkLmVycm9yLCB5bWF4ID0gQVJSICsgc3RkLmVycm9yKSwKICAjICAgICAgICAgICAgICAgd2lkdGggPSAwLjM1LCBsaW5ld2lkdGggPSAxLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC41KSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSA1LAogICAgcG9zaXRpb24gPSBwb3NpdGlvbl9kb2RnZSh3aWR0aCA9IDAuNSkpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgZ3VpZGVzKGNvbG91ciA9ICJub25lIikgKyAKICBsYWJzKHggPSAiU3BlY2llcyIsIAogICAgICAgeSA9ICJBUlIiLCAKICAgICAgIHNoYXBlID0gIkdyb3VwIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKY29lZl9saW1fcGxvdCA9IGdncGxvdChtbGVfQVJSLCBhZXMoeCA9IG1lYW5fY3RtYXgsIHkgPSBBUlIpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIGNvbG91ciA9ICJncmV5NzAiLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIpICsgCiAgIyBnZW9tX2Vycm9yYmFyKGFlcyhjb2xvdXIgPSBzcF9uYW1lLCB5bWluID0gQVJSIC0gc3RkLmVycm9yLCB5bWF4ID0gQVJSICsgc3RkLmVycm9yKSwKICAjICAgICAgICAgICAgICAgd2lkdGggPSAwLjUsIGxpbmV3aWR0aCA9IDEsIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArIAogIGdlb21fcG9pbnQoYWVzKGNvbG91ciA9IHNwX25hbWUsIHNoYXBlID0gc2V4ICksCiAgICAgICAgICAgICBzaXplID0gNSwKICAgIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjUpKSArCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgZ3VpZGVzKGNvbG91ciA9ICJub25lIikgKyAKICBsYWJzKHggPSAiTWVhbiBDVG1heCAowrBDKSIsIAogICAgICAgeSA9ICJBUlIiLCAKICAgICAgIHNoYXBlID0gIkdyb3VwIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQoKZ2dhcnJhbmdlKGNvZWZfcGxvdCwgY29lZl9saW1fcGxvdCwgY29tbW9uLmxlZ2VuZCA9IFQsIGxlZ2VuZCA9ICJyaWdodCIpCmBgYAoKIyMjIFNleCBhbmQgc3RhZ2UgdmFyaWF0aW9uIGluIHRoZXJtYWwgbGltaXRzIApQcmV2aW91cyBzZWN0aW9ucyBoYXZlIGdlbmVyYWxseSBsdW1wZWQganV2ZW5pbGUsIGZlbWFsZSwgYW5kIG1hbGUgaW5kaXZpZHVhbHMgdG9nZXRoZXIuIFRoZXJlIG1heSBiZSBpbXBvcnRhbnQgc3RhZ2UtIG9yIHNleC1zcGVjaWZpYyBkaWZmZXJlbmNlcyBpbiBDVG1heCB0aG91Z2guIEZvciBzZXZlcmFsIHNwZWNpZXMsIHdlIGhhdmUgbWVhc3VyZW1lbnRzIGZvciBpbmRpdmlkdWFscyBpbiBkaWZmZXJlbnQgc3RhZ2VzIG9yIG9mIGRpZmZlcmVudCBzZXhlcy4gCgpgYGB7ciBzZXgtc3RhZ2UtdGFibGV9CnNleF9zYW1wbGVfc2l6ZXMgPSBjdG1heF9yZXNpZHMgJT4lICAKICBncm91cF9ieShzcF9uYW1lLCBzZXgpICU+JSAgCiAgc3VtbWFyaXNlKG51bSA9IG4oKSkgJT4lICAKICBwaXZvdF93aWRlcihpZF9jb2xzID0gc3BfbmFtZSwKICAgICAgICAgICAgICBuYW1lc19mcm9tID0gc2V4LCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IG51bSwKICAgICAgICAgICAgICB2YWx1ZXNfZmlsbCA9IDApICU+JSAKICBzZWxlY3QoIlNwZWNpZXMiID0gc3BfbmFtZSwgIkp1dmVuaWxlIiA9IGp1dmVuaWxlLCAiRmVtYWxlIiA9IGZlbWFsZSwgIk1hbGUiID0gbWFsZSkKCmtuaXRyOjprYWJsZShzZXhfc2FtcGxlX3NpemVzLCBhbGlnbiA9ICJjIikKYGBgCgpUaGUgZmVtYWxlLW1hbGUgYW5kIGZlbWFsZS1qdXZlbmlsZSBjb21wYXJpc29ucyBzaG93IHRoYXQgdGhlcmUgYXJlIGdlbmVyYWxseSBubyBkaWZmZXJlbmNlcyBpbiB0aGVybWFsIGxpbWl0cyBiZXR3ZWVuIHRoZXNlIGdyb3Vwcy4gCgpgYGB7ciBjdG1heC1zZXgsIGZpZy53aWR0aD03LCBmaWcuaGVpZ2h0PTd9CmN0bWF4X3Jlc2lkcyAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBmaWx0ZXIoc2V4X3NhbXBsZV9zaXplcywgTWFsZSA+IDAsIEZlbWFsZSA+IDApJFNwZWNpZXMgJiAKICAgICAgICAgICBzZXggIT0gImp1dmVuaWxlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHNleCwgeSA9IHJlc2lkcywgY29sb3VyID0gc3BfbmFtZSwgZ3JvdXAgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKHNwX25hbWV+LiwgbmNvbCA9IDIpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAxKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDMsCiAgICAgICAgICAgICBhbHBoYSA9IDAuNSwKICAgICAgICAgICAgIHBvc2l0aW9uID0gcG9zaXRpb25faml0dGVyKGhlaWdodCA9IDAsIHdpZHRoID0gMC4wNSkpICsgIAogIGxhYnMoeCA9ICJTZXgiLCAKICAgICAgIHkgPSAiQ1RtYXggUmVzaWR1YWxzIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxOCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKYGBge3IgY3RtYXgtc3RhZ2UsIGZpZy53aWR0aD0zLCBmaWcuaGVpZ2h0PTZ9CmN0bWF4X3Jlc2lkcyAlPiUgCiAgZmlsdGVyKHNwX25hbWUgJWluJSBmaWx0ZXIoc2V4X3NhbXBsZV9zaXplcywgSnV2ZW5pbGUgPiAwICYgRmVtYWxlID4gMCkkU3BlY2llcyAmIAogICAgICAgICAgIHNleCAhPSAibWFsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBzZXgsIHkgPSByZXNpZHMsIGNvbG91ciA9IHNwX25hbWUsIGdyb3VwID0gc3BfbmFtZSkpICsgCiAgZmFjZXRfd3JhcChzcF9uYW1lfi4sIG5jb2wgPSAxKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMSkgKyAKICBnZW9tX3BvaW50KHNpemUgPSAzLAogICAgICAgICAgICAgYWxwaGEgPSAwLjUsCiAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX2ppdHRlcihoZWlnaHQgPSAwLCB3aWR0aCA9IDAuMDUpKSArICAKICBsYWJzKHggPSAiU2V4IiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9idyhiYXNlX3NpemUgPSAxOCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsIAogICAgICAgIHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKCmBgYHtyIHRyYWl0LXZhcmlhbmNlLWNvbGwtdGVtcCwgaW5jbHVkZSA9IEZ9CiMgCiMgR2l2ZW4gdGhlIGxvbmcgZ2VuZXJhdGlvbiB0aW1lcyBvZiB0aGVzZSBjb3BlcG9kcywgZGVjcmVhc2VzIGluIHRyYWl0IHZhcmlhbmNlIG1heSBpbmRpY2F0ZSBzZWxlY3Rpb24gb3ZlciB0aGUgc2Vhc29uYWwgY3ljbGUuIFNob3duIGJlbG93IGFyZSB0aGUgdmFyaWFuY2UgaW4gb2JzZXJ2ZWQgQ1RtYXggYW5kIHNpemUsIHBsb3R0ZWQgYWdhaW5zdCBjb2xsZWN0aW9uIGRhdGUuIFZhcmlhbmNlIGRlY3JlYXNlcyBpbiAqU2tpc3RvZGlhcHRvbXVzKiwgYnV0IHRoaXMgcGF0dGVybiBpcyBkcml2ZW4gYnkgYSBzaW5nbGUgY29sbGVjdGlvbiB3aXRoIGhpZ2ggdmFyaWFuY2UgZWFybHkgaW4gdGhlIHllYXIuIFNpemUgdmFyaWFuY2UgaW5jcmVhc2VzIHNsaWdodGx5IGluICpTa2lzdG9kaWFwdG9tdXMqLiBWYXJpYW5jZSBpbiBib3RoIENUbWF4IGFuZCBzaXplIGlzIGZhaXJseSBjb25zdGFudCBpbiAqTGVwdG9kaWFwdG9tdXMgbWludXR1cyosIHRoZSBvbmx5IG90aGVyIHNwZWNpZXMgY29sbGVjdGVkIGFjcm9zcyB0aGUgZW50aXJlIHNldCBvZiBzYW1wbGVzIHRodXMgZmFyLiAKIyAKIyBnZ3Bsb3QoZHJvcF9uYShhZHVsdF9zdW1tYXJpZXMsIGN0bWF4X3ZhciksIGFlcyh4ID0gYXMuRGF0ZShjb2xsZWN0aW9uX2RhdGUpLCB5ID0gY3RtYXhfdmFyLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKIyAgIGZhY2V0X3dyYXAoc3BfbmFtZX4uLCBzY2FsZXMgPSAiZnJlZV95IikgKyAKIyAgIGdlb21fcG9pbnQoc2l6ZSA9IDIpICsgCiMgICBnZW9tX3Ntb290aChzZSA9IEYpICsgCiMgICBsYWJzKHggPSAiQ29sbGVjdGlvbiBUZW1wLiAowrBDKSIsIAojICAgICAgICB5ID0gIkNUbWF4IFZhcmlhbmNlIikgKyAKIyAgIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAojICAgdGhlbWVfbWF0dF9mYWNldHMoKSArIAojICAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKQojIAojIGdncGxvdChkcm9wX25hKGFkdWx0X3N1bW1hcmllcywgc2l6ZV92YXIpLCBhZXMoeCA9IGFzLkRhdGUoY29sbGVjdGlvbl9kYXRlKSwgeSA9IHNpemVfdmFyLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKIyAgIGZhY2V0X3dyYXAoc3BfbmFtZX4uKSArIAojICAgZ2VvbV9wb2ludChzaXplID0gMikgKyAKIyAgIGdlb21fc21vb3RoKHNlID0gRikgKyAKIyAgIGxhYnMoeCA9ICJDb2xsZWN0aW9uIFRlbXAuICjCsEMpIiwgCiMgICAgICAgIHkgPSAiU2l6ZSBWYXJpYW5jZSIpICsgCiMgICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKIyAgIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKIyAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgoKIyMjIFRyYWl0IENvcnJlbGF0aW9ucyBhbmQgVHJhZGUtb2ZmcwoKQSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaXplIGFuZCB1cHBlciB0aGVybWFsIGxpbWl0cyBoYXMgYmVlbiBzdWdnZXN0ZWQgaW4gYSB3aWRlIHJhbmdlIG9mIG90aGVyIHRheGEuIFNob3duIGJlbG93IGFyZSB0aGUgbWVhc3VyZWQgdXBwZXIgdGhlcm1hbCBsaW1pdHMgcGxvdHRlZCBhZ2FpbnN0IHByb3NvbWUgbGVuZ3RoLiBUaGUgb3ZlcmFsbCByZWxhdGlvbnNoaXAgKGluY2x1c2l2ZSBvZiBhbGwgc3BlY2llcykgaXMgc2hvd24gYXMgdGhlIGJsYWNrIGxpbmUgaW4gdGhlIGJhY2tncm91bmQuIFJlZ3Jlc3Npb25zIGZvciBlYWNoIGluZGl2aWR1YWwgc3BlY2llcyBhcmUgYWxzbyBzaG93bi4gRm9yIHRoZSB0aHJlZSBkaWFwdG9taWRzIGFuZCAqRXBpc2NodXJhKiB0aGVyZSBpcyBhIHNsaWdodCBuZWdhdGl2ZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBzaXplIGFuZCB0aGVybWFsIGxpbWl0cy4gSG93ZXZlciwgYWNyb3NzIHRoZSBlbnRpcmUgYXNzZW1ibGFnZSwgdGhlcmUgaXMgYSBzbGlnaHQgaW5jcmVhc2UgaW4gdGhlcm1hbCBsaW1pdHMgd2l0aCBpbmNyZWFzaW5nIHNpemUuIFRoaXMgbWF5LCBob3dldmVyLCBiZSBkdWUgdG8gdGhlIHJlbGF0aXZlIG92ZXJyZXByZXNlbnRhdGlvbiBvZiBsYXJnZXIgc3VtbWVyIHNwZWNpZXMgbGlrZSAqU2tpc3RvZGlhcHRvbXVzKi4gSW5jcmVhc2luZyB0aGUgbWVhc3VyZW1lbnRzIG9uIGxhcmdlciwgY29sZC13YXRlciBzcGVjaWVzIGxpa2UgKkwuIHNpY2lsaXMqIGFuZCAqTGltbm9jYWxhbnVzKiBtYXkgYWx0ZXIgdGhpcyBvYnNlcnZlZCBwYXR0ZXJuLiAKCmBgYHtyIGN0bWF4LXNpemUsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03fQoKZnVsbF9kYXRhICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lICAKICBnZ3Bsb3QoIGFlcyh4ID0gc2l6ZSwgeSA9IGN0bWF4LCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBnZW9tX3Ntb290aChkYXRhID0gZnVsbF9kYXRhLCAKICAgICAgICAgICAgICBhZXMoeCA9IHNpemUsIHkgPSBjdG1heCksCiAgICAgICAgICAgICAgbWV0aG9kID0gImxtIiwgCiAgICAgICAgICAgICAgY29sb3VyID0iYmxhY2siLCAKICAgICAgICAgICAgICBsaW5ld2lkdGggPSAyLjUpICsgCiAgZ2VvbV9wb2ludChzaXplID0gMiwgYWxwaGEgPSAwLjgpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyKSArIAogIGxhYnMoeCA9ICJMZW5ndGggKG1tKSIsIAogICAgICAgeSA9ICJDVG1heCAowrBDKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpTaG93biBoZXJlIGlzIHRoZSByZWxhdGlvbnNoaXAgZm9yIGVhY2ggc3BlY2llcyBpbmRpdmlkdWFsbHkuIAoKYGBge3IgaW5kLXNwLWN0bWF4LXNpemUsIGZpZy53aWR0aD05LCBmaWcuaGVpZ2h0PTZ9CmZ1bGxfZGF0YSAlPiUgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lIGZpbHRlcihuKCkgPjIpICU+JSBmaWx0ZXIoIXN0cl9kZXRlY3Qoc3BfbmFtZSwgcGF0dGVybiA9ICJraW5kdGkiKSkgJT4lIAogIGdncGxvdCggYWVzKHggPSBzaXplLCB5ID0gY3RtYXgsIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGZhY2V0X3dyYXAoc3BfbmFtZX4uLCBzY2FsZXMgPSAiZnJlZSIsIG5yb3cgPSAyKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC44KSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiLAogICAgICAgY29sb3VyID0gIlNwZWNpZXMiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpgYGB7ciBtZWFuLWN0bWF4LW1lYW4tc2l6ZS1wbG90LCBmaWcud2lkdGg9OSwgZmlnLmhlaWdodD01fQpmdWxsX2RhdGEgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUsIHNleCkgJT4lIAogIHN1bW1hcml6ZShtZWFuX2N0bWF4ID0gbWVhbihjdG1heCwgbmEucm0gPSBUKSwKICAgICAgICAgICAgbWVhbl9zaXplID0gbWVhbihzaXplLCBuYS5ybSA9IFQpKSAlPiUgCiAgI2ZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAKICBnZ3Bsb3QoYWVzKHggPSBtZWFuX3NpemUsIHkgPSBtZWFuX2N0bWF4KSkgKyAKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBzZSA9IEYsIGxpbmV3aWR0aCA9IDIsIGNvbG91ciA9ICJibGFjayIpICsgCiAgZ2VvbV9wb2ludChhZXMoY29sb3VyID0gc3BfbmFtZSwgc2hhcGUgPSBzZXgpLAogICAgICAgICAgICAgc2l6ZSA9IDUpICsgCiAgbGFicyh4ID0gIkxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkNUbWF4ICjCsEMpIiwKICAgICAgIGNvbG91ciA9ICJTcGVjaWVzIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyIGN0bWF4cmVzaWRzLXNpemUsIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD03LCBpbmNsdWRlID0gRn0KY3RtYXhfcmVzaWRzICU+JSAKICAjZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogIGdncGxvdChhZXMoeCA9IHNpemVfcmVzaWRzLCB5ID0gcmVzaWRzLCBjb2xvdXIgPSBzcF9uYW1lKSkgKyAKICBmYWNldF93cmFwKHNwX25hbWV+LikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBsYWJzKHggPSAiTGVuZ3RoIChtbSkiLCAKICAgICAgIHkgPSAiQ1RtYXggKMKwQykiKSArIAogIHNjYWxlX2NvbG91cl9tYW51YWwodmFsdWVzID0gc3BlY2llc19jb2xzKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCgpTaG93biBoZXJlIGlzIHRoZSByZWxhdGlvbnNoaXAgYmV0d2VlbiBmZWN1bmRpdHkgYW5kIHNpemUsIHNob3dpbmcgdGhlIGNsYXNzaWMgcGF0dGVybiBvZiBpbmNyZWFzaW5nIGVnZyBwcm9kdWN0aW9uIHdpdGggaW5jcmVhc2luZyBzaXplLiAKCmBgYHtyIGZlY3VuZGl0eS1zaXplLCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KY3RtYXhfcmVzaWRzICU+JSAgCiAgZHJvcF9uYShmZWN1bmRpdHkpICU+JSAKZ2dwbG90KGFlcyh4ID0gc2l6ZSwgeSA9IGZlY3VuZGl0eSwgY29sb3VyID0gc3BfbmFtZSkpICsgCiAgZ2VvbV9zbW9vdGgobWV0aG9kID0gImxtIiwgc2UgPSBGLCBsaW5ld2lkdGggPSAyKSArIAogIGdlb21fcG9pbnQoc2l6ZSA9IDIsIGFscGhhID0gMC41KSArIAogIGxhYnMoeCA9ICJQcm9zb21lIGxlbmd0aCAobW0pIiwgCiAgICAgICB5ID0gIkZlY3VuZGl0eSAoIyBFZ2dzKSIsCiAgICAgICBjb2xvdXIgPSAiU3BlY2llcyIpICsgCiAgc2NhbGVfY29sb3VyX21hbnVhbCh2YWx1ZXMgPSBzcGVjaWVzX2NvbHMpICsgCiAgdGhlbWVfbWF0dCgpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gInJpZ2h0IikKYGBgCgpJbmRpdmlkdWFscyBtYXkgYWxzbyBhbGxvY2F0ZSBlbmVyZ3kgdG8gZGlmZmVyZW50IGZpdG5lc3MgcmVsYXRlZCB0cmFpdHMsIHByaW9yaXRpemluZyByZXByb2R1Y3RpdmUgb3V0cHV0IG92ZXIgZW52aXJvbm1lbnRhbCB0b2xlcmFuY2UsIGZvciBleGFtcGxlLiBTaG93biBiZWxvdyBpcyB0aGUgcmVsYXRpb25zaGlwIGJldHdlZW4gQ1RtYXggcmVzaWR1YWxzIChhZ2FpbiwgY29udHJvbGxpbmcgZm9yIHRoZSBlZmZlY3RzIG9mIGNvbGxlY3Rpb24gdGVtcGVyYXR1cmUpIGFnYWluc3QgZmVjdW5kaXR5LiBXZSBjYW4gc2VlIGNsZWFybHkgdGhhdCBpbmRpdmlkdWFscyB3aXRoIGluY3JlYXNlZCBmZWN1bmRpdHkgYXJlIG5vdCBkZWNyZWFzaW5nIHRoZXJtYWwgbGltaXRzLCBzdWdnZXN0aW5nIHRoYXQgdGhlcmUgaXMgbm8gZW5lcmdldGljIHRyYWRlLW9mZiBiZXR3ZWVuIHRoZXNlIHRyYWl0cy4gCgpgYGB7ciwgY3RtYXgtZmVjdW5kaXR5LCBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9N30KY3RtYXhfcmVzaWRzICU+JSAgCiAgZHJvcF9uYShmZWN1bmRpdHkpICU+JSAKICBnZ3Bsb3QoYWVzKHkgPSByZXNpZHMsIHggPSBmZWN1bmRpdHksIGNvbG91ciA9IHNwX25hbWUpKSArIAogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNlID0gRiwgbGluZXdpZHRoID0gMikgKyAKICBnZW9tX3BvaW50KHNpemUgPSAyLCBhbHBoYSA9IDAuNSkgKyAKICBsYWJzKHkgPSAiQ1RtYXggKMKwQykiLCAKICAgICAgIHggPSAiRmVjdW5kaXR5ICgjIEVnZ3MpIikgKyAKICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IHNwZWNpZXNfY29scykgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCmBgYHtyfQppZihwcmVkaWN0X3Z1bG4gPT0gRil7CiAga25pdHI6OmtuaXRfZXhpdCgpCn0KYGBgCgoKIyMgUHJlZGljdGluZyBWdWxuZXJhYmlsaXR5IApVc2luZyB0aGUgb2JzZXJ2ZWQgdGhlcm1hbCBsaW1pdCBkYXRhLCB3ZSBjYW4gcHJvZHVjZSBhIGhpbmRjYXN0IG9mIHRoZXJtYWwgc3RyZXNzIGZvciBMYWtlIENoYW1wbGFpbiBjb3BlcG9kcy4gRm9yIHRoZXNlIGluaXRpYWwgYXNzYXlzLCB3ZSB3aWxsIGRlZmluZSB0aGVybWFsIHN0cmVzcyBhcyBhbnkgdGltZSB3aGVuIG1heGltdW0gZGFpbHkgd2F0ZXIgdGVtcGVyYXR1cmUgaXMgd2l0aGluIDLCsEMgb2YgY29wZXBvZCBDVG1heCBvciBoaWdoZXIuIFdlIHdpbGwgdXNlIHRocmVlIGRpZmZlcmVudCBzY2VuYXJpb3M6IDEpIHRoZSBhdmVyYWdlIENUbWF4IGZvciBlYWNoIHNwZWNpZXMsIDIpIENUbWF4IHByZWRpY3RlZCB1c2luZyBjb2xsZWN0aW9uIHRlbXBlcmF0dXJlcywgYW5kIDMpIGZvciBzcGVjaWVzIHRoYXQgaGF2ZSBzdWZmaWNpZW50IGRhdGEsIENUbWF4IHByZWRpY3RlZCB1c2luZyB3aGljaGV2ZXIgZW52aXJvbm1lbnRhbCBmYWN0b3IgaXMgdGhlIHN0cm9uZ2VzdCBjYW5kaWRhdGUgZm9yIGRyaXZpbmcgYWNjbGltYXRpb24uIEluIGFsbCBjYXNlcywgZGF0YSBpcyBmaWx0ZXJlZCB0byBqdXN0IHRoZXJtYWwgbGltaXRzIG9mIGFkdWx0IGZlbWFsZXMuIAoKIyMjIFNjZW5hcmlvIDEKYGBge3J9Cm1lYW5fY3RtYXggPSBmdWxsX2RhdGEgJT4lIAogIGZpbHRlcihzZXggPT0gImZlbWFsZSIpICU+JSAgCiAgZ3JvdXBfYnkoc3BfbmFtZSkgJT4lIAogIHN1bW1hcml6ZSgibWVhbl9jdG1heCIgPSBtZWFuKGN0bWF4KSkgJT4lIAogIGFycmFuZ2UobWVhbl9jdG1heCkKCmtuaXRyOjprYWJsZShtZWFuX2N0bWF4KQpgYGAKCmBgYHtyfQojICMgQ29uc3RydWN0cyB0aGUgVVJMIGZvciB0aGUgZnVsbCB0ZW1wZXJhdHVyZSBkYXRhIHNldDsgUlVOIFRISVMgT05DRQojIGhpbmRfdXJsID0gY29uc3RydWN0TldJU1VSTChzaXRlTnVtYmVycyA9IHNpdGVOdW1iZXIsIHBhcmFtZXRlckNkID0gcGFyYW1ldGVyQ2QsIHNlcnZpY2UgPSAidXYiKQojIAojIGhpbmRfdGVtcF9kYXRhID0gaW1wb3J0V2F0ZXJNTDEoaGluZF91cmwsIGFzRGF0ZVRpbWUgPSBUKSAlPiUKIyAgIG11dGF0ZSgiZGF0ZSIgPSBhcy5EYXRlKGRhdGVUaW1lKSkgJT4lCiMgICBzZWxlY3QoZGF0ZSwgInRlbXAiID0gWF8wMDAxMF8wMDAwMCkKIyAKIyB3cml0ZS50YWJsZSh4ID0gaGluZF90ZW1wX2RhdGEsIGZpbGUgPSAiaGluZGNhc3RfdGVtcHMuY3N2Iiwgcm93Lm5hbWVzID0gRiwgc2VwID0gIiwiKQpgYGAKCmBgYHtyfQojIGdncGxvdChoaW5kX3RlbXBfZGF0YSwgYWVzKHggPSBkYXRlLCB5ID0gdGVtcCkpICsgCiMgICBnZW9tX2xpbmUobGluZXdpZHRoID0gMC4xKSArIAojICAgbGFicyh4ID0gIkRhdGUiLCAKIyAgICAgICAgeSA9ICJXYXRlciBUZW1wZXJhdHVyZSAowrBDKSIpICsKIyAgIHRoZW1lX21hdHQoKQpgYGAKCkluIHRoZSBzaW1wbGVzdCBzY2VuYXJpbywgc3BlY2llcyB0aGVybWFsIGxpbWl0cyBhcmUgc3RhdGljIHRocm91Z2ggdGltZSwgcmVwcmVzZW50ZWQgYnkgdGhlIGF2ZXJhZ2UgQ1RtYXggb2YgYWR1bHQgZmVtYWxlIGNvcGVwb2RzLiBJbiB0aGlzIHNjZW5hcmlvLCBvbmx5IHRocmVlIG9mIHRoZSBzZXZlbiBvYnNlcnZlZCBzcGVjaWVzIGFyZSBleHBvc2VkIHRvIHRoZXJtYWwgc3RyZXNzICh0ZW1wZXJhdHVyZXMgd2l0aGluIDXCsEMgb2YgQ1RtYXgpLiBUZW1wZXJhdHVyZXMgYXBwcm9hY2hlZCB0aGUgdGhlcm1hbCBsaW1pdCBvZiAqTGVwdG9kaWFwdG9tdXMgc2ljaWxpcyogb24gYSBoYW5kZnVsIG9mIGRheXMuIEJ5IGNvbnRyYXN0LCAqU2VuZWNlbGxhIGNhbGFub2lkZXMqIGFuZCAqTGltbm9jYWxhbnVzIG1hY3J1cnVzKiB3ZXJlIGJvdGggZXhwb3NlZCB0byBzdWJzdGFudGlhbCB0aGVybWFsIHN0cmVzcyB0aHJvdWdob3V0IGEgbGFyZ2UgcG9ydGlvbiBvZiB0aGUgeWVhciwgbGlrZWx5IGV4cGxhaW5pbmcgd2h5IHRoZXNlIHNwZWNpZXMgYXJlIGFic2VudCBmcm9tIHRoZSBjb21tdW5pdHkgZm9yIHRoZSBzdW1tZXIgYW5kIGZhbGwgcGVyaW9kcy4gCgpgYGB7ciBmaWcud2lkdGg9MTAsIGZpZy5oZWlnaHQ9NX0KaGluZDFfZGF0YSA9IGhpbmRfdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXplKCJkYWlseV9tYXgiID0gbWF4KHRlbXApLAogICAgICAgICAgICAiZGFpbHlfbWVhbiIgPSBtZWFuKHRlbXApLCkgJT4lIAogIGJpbmRfY29scyhwaXZvdF93aWRlcihtZWFuX2N0bWF4LCBuYW1lc19mcm9tID0gc3BfbmFtZSwgdmFsdWVzX2Zyb20gPSBtZWFuX2N0bWF4KSkgJT4lICAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUsIC1kYWlseV9tYXgsIC1kYWlseV9tZWFuKSwKICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAic3BlY2llcyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAibWVhbl9jdG1heCIpICU+JSAgCiAgbXV0YXRlKGxpbV9kaWZmID0gbWVhbl9jdG1heCAtIGRhaWx5X21heCkgJT4lICAKICBtdXRhdGUoZG95ID0geWRheShkYXRlKSwKICAgICAgICAgIm1ldGhvZCIgPSAiTm9fYWNjbGltYXRpb24iKQoKaGluZF9kYWlseV90ZW1wX2RhdGEgPSBoaW5kX3RlbXBfZGF0YSAlPiUKICB1bmdyb3VwKCkgJT4lIAogIGdyb3VwX2J5KGRhdGUpICU+JSAKICBzdW1tYXJpc2UobWVhbl90ZW1wID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgbWVkX3RlbXAgPSBtZWRpYW4odGVtcCksCiAgICAgICAgICAgIHZhcl90ZW1wID0gdmFyKHRlbXApLCAKICAgICAgICAgICAgbWluX3RlbXAgPSBtaW4odGVtcCksIAogICAgICAgICAgICBtYXhfdGVtcCA9IG1heCh0ZW1wKSkgJT4lIAogIG11dGF0ZSgicmFuZ2VfdGVtcCIgPSBtYXhfdGVtcCAtIG1pbl90ZW1wKQoKI3RhYmxlKGhpbmQxX2RhdGEkc3BlY2llcykKCmhpbmQxX2RhdGEgJT4lIAogIGZpbHRlcihsaW1fZGlmZiA8PSA1KSAlPiUgIAogIGdncGxvdChhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBzcGVjaWVzKSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgCiAgICAgICAgICAgICBjb2xvdXIgPSAiZ3JleSIpICsgCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKwogIGdlb21fc21vb3RoKHNlID0gRikgKyAKICBsYWJzKHggPSAiRGF5IG9mIFllYXIiLCAKICAgICAgIHkgPSAiUHJlZGljdGVkIFdhcm1pbmcgVG9sZXJhbmNlIFxuKMKwQyBBYm92ZSBEYWlseSBNYXgpIikgKyAKICB0aGVtZV9tYXR0KCkgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiKQpgYGAKCiMjIyBTY2VuYXJpbyAyCkluIHRoZSBzZWNvbmQgc2NlbmFyaW8sIHRoZXJtYWwgbGltaXRzIHZhcnkgd2l0aGluIGFuZCBiZXR3ZWVuIHNwZWNpZXMuIEEgc2ltcGxlIG1vZGVsIGlzIHVzZWQgdG8gcHJlZGljdCBzcGVjaWVzIHRoZXJtYWwgbGltaXRzIGJhc2VkIG9uIG1lYW4gZGFpbHkgdGVtcGVyYXR1cmUgKENUbWF4IGFzIGEgZnVuY3Rpb24gb2Ygc3BlY2llcyBhbmQgY29sbGVjdGlvbiB0ZW1wZXJhdHVyZSwgYnV0IHdpdGhvdXQgdGhlIGludGVyYWN0aW9uIGJldHdlZW4gdGhlc2UgdHdvIGZhY3RvcnMpLiBUaGVzZSBwcmVkaWN0ZWQgdGhlcm1hbCBsaW1pdHMgYXJlIHRoZW4gY29tcGFyZWQgYWdhaW5zdCB0aGUgbWF4aW11bSBkYWlseSB0ZW1wZXJhdHVyZSB0byBlc3RpbWF0ZSB0aGVybWFsIHN0cmVzcywgYXMgaW4gU2NlbmFyaW8gMS4gSW5jbHVkaW5nIHRoaXMgc2ltcGxlIGZvcm0gb2YgYWNjbGltYXRpb24gaW4gdGhlIG1vZGVsIHJlZHVjZWQgdGhlIGRlZ3JlZSBvZiB0aGVybWFsIHN0cmVzcyBmb3IgZWFjaCBzcGVjaWVzLCBlbGltaW5hdGluZyBpdCBlbnRpcmVseSBmb3IgKkxlcHRvZGlhcHRvbXVzIHNpY2lsaXMqLiBOb3RlIHRoYXQgdGhlIG1hZ25pdHVkZSBvZiB0aGUgcHJlZGljdGVkIHN0cmVzcyBpcyAgbG93IGVub3VnaCB0aGF0IHJlbW92aW5nIHRoZSA1wrBDIGJ1ZmZlciBhcm91bmQgdGhlIHByZWRpY3RlZCB0aGVybWFsIGxpbWl0cyB3b3VsZCBhY3R1YWxseSBsaW1pdCBwcmVkaWN0ZWQgdGhlcm1hbCBzdHJlc3MgdG8ganVzdCBhIGZldyBkYXlzIGZvciAqU2VuZWNlbGxhIGNhbGFub2lkZXMqLiAKCmBgYHtyIGZpZy5oZWlnaHQ9NSwgZmlnLndpZHRoPTEwfQpoaW5kY2FzdF9tb2RlbDEgPSBsbShkYXRhID0gZmlsdGVyKGZ1bGxfZGF0YSwgc2V4ID09ICJmZW1hbGUiKSwKICAgICAgICAgICAgICAgICAgICAgY3RtYXggfiBjb2xsZWN0aW9uX3RlbXAgKyBzcF9uYW1lKQoKaGluZDJfZGF0YSA9IGhpbmRfdGVtcF9kYXRhICU+JSAKICBncm91cF9ieShkYXRlKSAlPiUgCiAgc3VtbWFyaXplKCJjb2xsZWN0aW9uX3RlbXAiID0gbWVhbih0ZW1wKSwKICAgICAgICAgICAgImRhaWx5X21heCIgPSBtYXgodGVtcCkpICU+JSAKICBiaW5kX2NvbHMoCiAgICBwaXZvdF93aWRlcihtZWFuX2N0bWF4LCAKICAgICAgICAgICAgICAgIG5hbWVzX2Zyb20gPSBzcF9uYW1lLCAKICAgICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gbWVhbl9jdG1heCkpICU+JSAKICBwaXZvdF9sb25nZXIoY29scyA9IGMoLWRhdGUsIC1kYWlseV9tYXgsIC1jb2xsZWN0aW9uX3RlbXApLAogICAgICAgICAgICAgICBuYW1lc190byA9ICJzcF9uYW1lIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJtZWFuX2N0bWF4IikgJT4lIAogIHNlbGVjdCgtbWVhbl9jdG1heCkgJT4lIAogIG11dGF0ZSgicHJlZF9jdG1heCIgPSBwcmVkaWN0LmxtIChoaW5kY2FzdF9tb2RlbDEsIG5ld2RhdGEgPSAuKSkgJT4lIAogIHNlbGVjdChkYXRlLCAiZGFpbHlfbWVhbiIgPSBjb2xsZWN0aW9uX3RlbXAsIGRhaWx5X21heCwgInNwZWNpZXMiID0gc3BfbmFtZSwgcHJlZF9jdG1heCkgJT4lIAogIG11dGF0ZShsaW1fZGlmZiA9IHByZWRfY3RtYXggLSBkYWlseV9tYXgpICU+JSAKICAjZmlsdGVyKGxpbV9kaWZmIDw9IDApICU+JSAgCiAgbXV0YXRlKGRveSA9IHlkYXkoZGF0ZSksCiAgICAgICAgICJtZXRob2QiID0gIkNvbnN0YW50X2FjY2xpbWF0aW9uIikKCiMgZ2dwbG90KGhpbmQyX2RhdGEsIGFlcyh4ID0gZGFpbHlfbWVhbiwgeSA9IHByZWRfY3RtYXgsIGNvbG91ciA9IHNwZWNpZXMpKSArCiMgICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSAKCiMgdGFibGUoaGluZDJfZGF0YSRzcGVjaWVzKQpoaW5kMl9kYXRhICU+JSAgCiAgZmlsdGVyKGxpbV9kaWZmIDw9IDUpICU+JSAgCiAgZ2dwbG90KGFlcyh4ID0gZG95LCB5ID0gbGltX2RpZmYsIGNvbG91ciA9IHNwZWNpZXMpKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMCkgKyAKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQgPSA1LCAKICAgICAgICAgICAgIGNvbG91ciA9ICJncmV5IikgKyAKICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgZ2VvbV9zbW9vdGgoKSArIAogIGxhYnMoeCA9ICJEYXkgb2YgWWVhciIsIAogICAgICAgeSA9ICJQcmVkaWN0ZWQgV2FybWluZyBUb2xlcmFuY2UgXG4owrBDIEFib3ZlIERhaWx5IE1heCkiKSArIAogIHRoZW1lX21hdHQoKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKIyMjIFNjZW5hcmlvIDMKVGhlIGZpbmFsIHNjZW5hcmlvIGFsbG93cyB0aGUgZW52aXJvbm1lbnRhbCB2YXJpYWJsZSB1c2VkIHRvIHByZWRpY3QgQ1RtYXggdG8gdmFyeSBiZXR3ZWVuIHNwZWNpZXMuIEZvciBzcGVjaWVzIG9ic2VydmVkIGluIGZld2VyIHRoYW4gNSBjb2xsZWN0aW9ucywgd2UgdXNlIHRoZSBzYW1lIGFwcHJvYWNoIGFzIGluIFNjZW5hcmlvIDIuIEZvciBzcGVjaWVzIG9ic2VydmVkIGluIG1vcmUgdGhhbiA1IGNvbGxlY3Rpb25zLCBob3dldmVyLCB0aGUgZmFjdG9yIHdpdGggdGhlIHN0cm9uZ2VzdCBjb3JyZWxhdGlvbiB3aXRoIENUbWF4IGlzIHVzZWQgdG8gcHJlZGljdCB0aGVybWFsIGxpbWl0cy4gVGhlc2UgZmFjdG9ycyBhcmUgaW5jbHVkZWQgYmVsb3cuCgpgYGB7cn0KaGluZF9wcmVkcyA9IGNvcnJfdmFscyAlPiUgIAogIGZpbHRlcihzaWcgPT0gIlNpZy4iKSAlPiUgCiAgZHJvcF9uYShjb3JyZWxhdGlvbikgJT4lIAogIGdyb3VwX2J5KHNwX25hbWUpICU+JQogIGFycmFuZ2UoZGVzYyhjb3JyZWxhdGlvbikpICU+JSAKICBzbGljZV9oZWFkKG4gPSAxKSAlPiUgCiAgc2VsZWN0KCJTcGVjaWVzIiA9IHNwX25hbWUsICJQcmVkaWN0b3IiID0gcGFyYW1ldGVyLCAiRHVyYXRpb24iID0gZHVyYXRpb24sICJDb3JyZWxhdGlvbiIgPSBjb3JyZWxhdGlvbiwgIlAtVmFsdWUiID0gcC52YWx1ZSkKCmtuaXRyOjprYWJsZShoaW5kX3ByZWRzLCBhbGlnbiA9ICJjIikKYGBgCgpgYGB7cn0KaGluZDNfZGF0YSA9IGhpbmQyX2RhdGEgJT4lICMgQ29udGFpbnMgZGF0YSBmb3Igc3BlY2llcyB0aGF0IHdvbid0IGNoYW5nZSBmcm9tIHNjZW5hcmlvIDIKICBmaWx0ZXIoIShzcGVjaWVzICVpbiUgY29ycl92YWxzJHNwX25hbWUpKQoKcHJlZHNfdG9fcHVsbCA9IGhpbmRfcHJlZHMgJT4lICAKICBzZWxlY3QoU3BlY2llcywgUHJlZGljdG9yLCBEdXJhdGlvbikgCgpmb3IoaSBpbiAxOmxlbmd0aChwcmVkc190b19wdWxsJFNwZWNpZXMpKXsKICAKICBpZihwcmVkc190b19wdWxsJER1cmF0aW9uW2ldID09ICJwcmlvciIpeyAjVGhlIHByaW9yIGRheSB0ZW1wZXJhdHVyZSBtZXRyaWNzIHNob3VsZCBiZSB1c2VkCiAgICBkdXJhdGlvbiA9IE5BCiAgICAKICAgIHByZWRpY3RvcnMgPSBoaW5kX2RhaWx5X3RlbXBfZGF0YSAlPiUgCiAgICAgIG11dGF0ZShkYXRlID0gZGF0ZSArIDEpIAogICAgCiAgICBwYXJhbWV0ZXIgPSBwcmVkc190b19wdWxsJFByZWRpY3RvcltpXQogICAgCiAgICBtb2RlbF9kYXRhID0gZnVsbF9kYXRhICU+JQogICAgICBmaWx0ZXIoc3BfbmFtZSAlaW4lIHByZWRzX3RvX3B1bGwkU3BlY2llc1tpXSkgJT4lIAogICAgICBmaWx0ZXIoc2V4ID09ICJmZW1hbGUiKSAlPiUgCiAgICAgIG11dGF0ZShjb2xsZWN0aW9uX2RhdGUgPSBhc19kYXRlKGNvbGxlY3Rpb25fZGF0ZSkpICU+JSAKICAgICAgaW5uZXJfam9pbihwcmVkaWN0b3JzLCBqb2luX2J5KGNvbGxlY3Rpb25fZGF0ZSA9PSBkYXRlKSkgJT4lICAKICAgICAgc2VsZWN0KGN0bWF4LCBjb250YWlucyhwYXJhbWV0ZXIpKQogICAgCiAgICBpZihkaW0obW9kZWxfZGF0YSlbMl0gPT0gMil7CiAgICAgIGhpbmQubW9kZWwgPSBsbShkYXRhID0gbW9kZWxfZGF0YSwgCiAgICAgICAgICAgICAgICAgICAgICBjdG1heCB+IC4pCiAgICAgIAogICAgICBzcF9kYXRhID0gcHJlZGljdG9ycyAlPiUgCiAgICAgICAgc2VsZWN0KGRhdGUsIGNvbnRhaW5zKHBhcmFtZXRlcikpICU+JSAKICAgICAgICBtdXRhdGUocHJlZF9jdG1heCA9IHByZWRpY3QoaGluZC5tb2RlbCwgbmV3ZGF0YSA9IC4pKSAlPiUgIAogICAgICAgIHNlbGVjdChkYXRlLCBwcmVkX2N0bWF4KSAlPiUgCiAgICAgICAgaW5uZXJfam9pbihoaW5kX2RhaWx5X3RlbXBfZGF0YSwgYnkgPSBjKCJkYXRlIikpICU+JSAKICAgICAgICBtdXRhdGUoInNwZWNpZXMiID0gcHJlZHNfdG9fcHVsbCRTcGVjaWVzW2ldLAogICAgICAgICAgICAgICAiZG95IiA9IHlkYXkoZGF0ZSksCiAgICAgICAgICAgICAgIGxpbV9kaWZmID0gcHJlZF9jdG1heCAtIG1heF90ZW1wKSAlPiUgCiAgICAgICAgc2VsZWN0KGRhdGUsIGRhaWx5X21lYW4gPSBtZWFuX3RlbXAsIGRhaWx5X21heCA9IG1heF90ZW1wLCBzcGVjaWVzLCBwcmVkX2N0bWF4LCBsaW1fZGlmZiwgZG95KQogICAgICAKICAgICAgaGluZDNfZGF0YSA9IGJpbmRfcm93cyhoaW5kM19kYXRhLCBzcF9kYXRhKQogICAgfWVsc2V7CiAgICAgIHByaW50KCJUb28gbWFueSBjb2x1bW5zIHNlbGVjdGVkIikKICAgIH0KICAgIAogICAgCiAgfWVsc2V7CiAgICBkdXJhdGlvbiA9IGFzLm51bWVyaWMocHJlZHNfdG9fcHVsbCREdXJhdGlvbltpXSkKICB9CiAgCiAgaWYocHJlZHNfdG9fcHVsbCREdXJhdGlvbltpXSAhPSAicHJpb3IiICYgaXMubmEoZHVyYXRpb24pKXsgI0RhaWx5IHRlbXBlcmF0dXJlcyBzaG91bGQgYmUgdXNlZCwgYXMgaW4gU2NlbmFyaW8gMgogICAgc3BfZGF0YSA9IGhpbmQyX2RhdGEgJT4lIAogICAgICBmaWx0ZXIoc3BlY2llcyA9PSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0pCiAgICAKICAgIGhpbmQzX2RhdGEgPSBiaW5kX3Jvd3MoaGluZDNfZGF0YSwgc3BfZGF0YSkKICB9CiAgCiAgaWYoaXMubnVtZXJpYyhkdXJhdGlvbikpewogICAgI05laXRoZXIgdGhlIHByaW9yIGRheSBub3IgZGF5IG9mIG1ldHJpY3Mgc2hvdWxkIGJlIHVzZWQ7IHVzZSBkdXJhdGlvbiBhcyBuX2RheXMKICAgIAogICAgcHJlZGljdG9ycyA9IGdldF9wcmVkaWN0b3JzKGRhaWx5X3ZhbHVlcyA9IGhpbmRfZGFpbHlfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByYXdfdGVtcCA9IGhpbmRfdGVtcF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuX2RheXMgPSBkdXJhdGlvbikKICAgIAogICAgcGFyYW1ldGVyID0gcHJlZHNfdG9fcHVsbCRQcmVkaWN0b3JbaV0KICAgIAogICAgbW9kZWxfZGF0YSA9IGZ1bGxfZGF0YSAlPiUKICAgICAgZmlsdGVyKHNwX25hbWUgJWluJSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0pICU+JSAKICAgICAgZmlsdGVyKHNleCA9PSAiZmVtYWxlIikgJT4lIAogICAgICBtdXRhdGUoY29sbGVjdGlvbl9kYXRlID0gYXNfZGF0ZShjb2xsZWN0aW9uX2RhdGUpKSAlPiUgCiAgICAgIGlubmVyX2pvaW4ocHJlZGljdG9ycywgam9pbl9ieShjb2xsZWN0aW9uX2RhdGUgPT0gZGF0ZSkpICU+JSAgCiAgICAgIHNlbGVjdChjdG1heCwgY29udGFpbnMocGFzdGUoImRheV8iLCBwYXJhbWV0ZXIsIHNlcCA9ICIiKSkpCiAgICAKICAgIGlmKGRpbShtb2RlbF9kYXRhKVsyXSA9PSAyKXsKICAgICAgaGluZC5tb2RlbCA9IGxtKGRhdGEgPSBtb2RlbF9kYXRhLCAKICAgICAgICAgICAgICAgICAgICAgIGN0bWF4IH4gLikKICAgICAgCiAgICAgIHNwX2RhdGEgPSBwcmVkaWN0b3JzICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgY29udGFpbnMocGFyYW1ldGVyKSkgJT4lIAogICAgICAgIG11dGF0ZShwcmVkX2N0bWF4ID0gcHJlZGljdChoaW5kLm1vZGVsLCBuZXdkYXRhID0gLikpICU+JSAgCiAgICAgICAgc2VsZWN0KGRhdGUsIHByZWRfY3RtYXgpICU+JSAKICAgICAgICBpbm5lcl9qb2luKGhpbmRfZGFpbHlfdGVtcF9kYXRhLCBieSA9IGMoImRhdGUiKSkgJT4lIAogICAgICAgIG11dGF0ZSgic3BlY2llcyIgPSBwcmVkc190b19wdWxsJFNwZWNpZXNbaV0sCiAgICAgICAgICAgICAgICJkb3kiID0geWRheShkYXRlKSwKICAgICAgICAgICAgICAgbGltX2RpZmYgPSBwcmVkX2N0bWF4IC0gbWF4X3RlbXApICU+JSAKICAgICAgICBzZWxlY3QoZGF0ZSwgZGFpbHlfbWVhbiA9IG1lYW5fdGVtcCwgZGFpbHlfbWF4ID0gbWF4X3RlbXAsIHNwZWNpZXMsIHByZWRfY3RtYXgsIGxpbV9kaWZmLCBkb3kpCiAgICAgIAogICAgICBoaW5kM19kYXRhID0gYmluZF9yb3dzKGhpbmQzX2RhdGEsIHNwX2RhdGEpCiAgICAgIAogICAgfWVsc2V7CiAgICAgIHByaW50KCJUb28gbWFueSBjb2x1bW5zIHNlbGVjdGVkIikKICAgIH0KICAgIAogIH0KfQoKaGluZDNfZGF0YSA9IGhpbmQzX2RhdGEgJT4lIAogIG11dGF0ZSgibWV0aG9kIiA9ICJWYXJpYWJsZV9hY2NsaW1hdGlvbiIpCmBgYAoKVGhpcyB0aGlyZCBhcHByb2FjaCBkaWQgbm90IGFmZmVjdCB0aGUgcHJlZGljdGVkIHBhdHRlcm5zIGluICpMaW1ub2NhbGFudXMqIG9yICpTZW5lY2VsbGEqIChuZWl0aGVyIHNwZWNpZXMgaGFzIGJlZW4gb2JzZXJ2ZWQgaW4gZW5vdWdoIGNvbGxlY3Rpb25zIHRvIGVzdGltYXRlIHRoZSBlZmZlY3RzIG9mIGRpZmZlcmVudCBlbnZpcm9ubWVudGFsIGZhY3RvcnMpLiBDaGFuZ2luZyB0aGUgYWNjbGltYXRpb24gYXBwcm9hY2ggZGlkIGFmZmVjdCBwYXR0ZXJucyBpbiB0aGVybWFsIGxpbWl0cyBpbiB0aGUgb3RoZXIgc3BlY2llcyB0aG91Z2guIFRoZSBmaWd1cmUgYmVsb3cgc2hvd3MgaG93IHByZWRpY3RlZCB3YXJtaW5nIHRvbGVyYW5jZSB2YXJpZXMgb3ZlciB0aGUgeWVhciBpbiB0aGUgc2V2ZW4gc3BlY2llcywgYmFzZWQgb24gdGhlIHRocmVlIGRpZmZlcmVudCBwcmVkaWN0aW9uIG1ldGhvZHMuIEluIGdlbmVyYWwsIGNvbnN0YW50IHRoZXJtYWwgbGltaXRzICh0aGUgJ25vIGFjY2xpbWF0aW9uJyBtZXRob2QpIHJlc3VsdGVkIGluIGxhcmdlciB3YXJtaW5nIHRvbGVyYW5jZSBkdXJpbmcgdGhlIHdpbnRlciBhbmQgbG93ZXIgd2FybWluZyB0b2xlcmFuY2UgZHVyaW5nIHRoZSBzdW1tZXIsIGFsdGhvdWdoIHRoaXMgZWZmZWN0IHdhcyBzbWFsbCBpbiBtb3N0IHNwZWNpZXMuICAgICAKCmBgYHtyIGZpZy53aWR0aD0xMCwgZmlnLmhlaWdodD0xMH0Kc3ludGhlc2lzID0gYmluZF9yb3dzKAogIHNlbGVjdChoaW5kMV9kYXRhLCBkYXRlLCBkb3ksIGRhaWx5X21lYW4sIGRhaWx5X21heCwgc3BlY2llcywgInByZWRfY3RtYXgiID0gbWVhbl9jdG1heCwgbGltX2RpZmYsIG1ldGhvZCksCiAgc2VsZWN0KGhpbmQyX2RhdGEsIGRhdGUsIGRveSwgZGFpbHlfbWVhbiwgZGFpbHlfbWF4LCAgc3BlY2llcywgcHJlZF9jdG1heCwgbGltX2RpZmYsIG1ldGhvZCksCiAgc2VsZWN0KGhpbmQzX2RhdGEsIGRhdGUsIGRveSwgZGFpbHlfbWVhbiwgZGFpbHlfbWF4LCAgc3BlY2llcywgcHJlZF9jdG1heCwgbGltX2RpZmYsIG1ldGhvZCkpICU+JSAKICBtdXRhdGUobWV0aG9kID0gZmN0X3JlbGV2ZWwobWV0aG9kLCAiTm9fYWNjbGltYXRpb24iLCAiQ29uc3RhbnRfYWNjbGltYXRpb24iLCAiVmFyaWFibGVfYWNjbGltYXRpb24iKSkKCmNsaW1hdG9sb2d5ID0gc3ludGhlc2lzICU+JSAKICBncm91cF9ieShzcGVjaWVzLCBkb3ksIG1ldGhvZCkgJT4lICAKICBzdW1tYXJpc2UoIm1lYW5fZGlmZiIgPSBtZWFuKGxpbV9kaWZmKSwKICAgICAgICAgICAgIm1pbl9kaWZmIiA9IG1pbihsaW1fZGlmZiksCiAgICAgICAgICAgICJtYXhfZGlmZiIgPSBtYXgobGltX2RpZmYpKSAlPiUgCiAgbXV0YXRlKG1ldGhvZCA9IGZjdF9yZWxldmVsKG1ldGhvZCwgIk5vX2FjY2xpbWF0aW9uIiwgIkNvbnN0YW50X2FjY2xpbWF0aW9uIiwgIlZhcmlhYmxlX2FjY2xpbWF0aW9uIikpCgphY2NfZWZmZWN0cyA9IHN5bnRoZXNpcyAlPiUgCiAgcGl2b3Rfd2lkZXIoaWRfY29scyA9IGMoZGF0ZSwgc3BlY2llcywgZG95KSwgCiAgICAgICAgICAgICAgbmFtZXNfZnJvbSA9IG1ldGhvZCwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSBsaW1fZGlmZikgJT4lICAKICBtdXRhdGUoImNvbnN0X2FjY19lZmZlY3QiID0gQ29uc3RhbnRfYWNjbGltYXRpb24gLSBOb19hY2NsaW1hdGlvbiwKICAgICAgICAgInZhcl9hY2NfZWZmZWN0IiA9IFZhcmlhYmxlX2FjY2xpbWF0aW9uIC0gTm9fYWNjbGltYXRpb24pCgpnZ3Bsb3Qoc3ludGhlc2lzLCBhZXMoeCA9IGRveSwgeSA9IGxpbV9kaWZmLCBjb2xvdXIgPSBtZXRob2QpKSArIAogIGZhY2V0X3dyYXAoc3BlY2llc34uKSArIAogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApICsgCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gNSwgY29sb3VyID0gImdyZXkiKSArIAogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjEpICsgCiAgbGFicyh4ID0gIkRheSBvZiBZZWFyIiwgCiAgICAgICB5ID0gIlByZWRpY3RlZCBXYXJtaW5nIFRvbGVyYW5jZSAowrBDIEFib3ZlIERhaWx5IE1heCkiKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKGJhc2Vfc2l6ZSA9IDE4KSArIAogIHRoZW1lKHN0cmlwLnRleHQueC50b3AgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDEwKSkKYGBgCgpgYGB7ciwgaW5jbHVkZSA9IEZ9CnllYXJseV9zdW1tYXJ5ID0gc3ludGhlc2lzICU+JSAgCiAgbXV0YXRlKCJ5ZWFyIiA9IHllYXIoZGF0ZSkpICU+JSAKICBncm91cF9ieShzcGVjaWVzLCB5ZWFyLCBtZXRob2QpICU+JSAKICAgIHN1bW1hcmlzZSgibWluX3d0IiA9IG1pbihsaW1fZGlmZiksCiAgICAgICAgICAgICAgIm1heF93dCIgPSBtYXgobGltX2RpZmYpKSAlPiUgCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKG1pbl93dCwgbWF4X3d0KSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIm1ldHJpYyIsIAogICAgICAgICAgICAgICB2YWx1ZXNfdG8gPSAid3QiKQoKZ2dwbG90KHllYXJseV9zdW1tYXJ5LCBhZXMoeCA9IG1ldGhvZCwgeSA9IHd0LCBjb2xvdXIgPSBtZXRyaWMpKSArIAogIGZhY2V0X3dyYXAoLn5zcGVjaWVzKSArIAogIGdlb21fcG9pbnQoKSArIAogIHRoZW1lX21hdHRfZmFjZXRzKCkgKyAKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDMwMCwgaGp1c3QgPSAwLCB2anVzdCA9IDAuNSkpCmBgYAoK